在HTML画布中添加字母间距 [英] Adding Letter Spacing in HTML Canvas

查看:191
本文介绍了在HTML画布中添加字母间距的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经阅读了很多StackOverflow的答案和其他页面谈论如何在Canvas中做字母间距。其中最有用的是画布元素中的字母间距

I've read a lot of StackOverflow answers and other pages talking about how to do letter spacing in Canvas. One of the more useful ones was Letter spacing in canvas element

正如其他问题所说,我有这个画布元素,我正在绘制文本。我想设置字母间距类似于CSS字母间距属性。这是我的意思是增加字符之间的字符之间的像素数量,当一个字符串被绘制时。'请注意,字母间距有时,不正确,称为字距调整。

As that other question said, 'I've got this canvas element that I'm drawing text to. I want to set the letter spacing similar to the CSS letter-spacing attribute. By that I mean increasing the amount of pixels between letters when a string is drawn.' Note that letter spacing is sometimes, and incorrectly, referred to as kerning.

一般的方法似乎是逐个字母输出字符串,使用measureText(letter)得到字母的宽度,然后添加额外的间距。这样的问题是它没有考虑字母间距对等。有关此和相关注释的示例,请参阅上面的链接。

I notice that the general approach seems to be to output the string on a letter by letter basis, using measureText(letter) to get the letter's width and then adding additional spacing. The problem with this is it doesn't take into account letter kerning pairs and the like. See the above link for an example of this and related comments.

似乎是这样做的,对于间距为spacing的行间距,将是这样:

Seems to me that the way to do it, for a line spacing of 'spacing', would be to do something like:


  1. 从位置(X,Y)开始。

  2. 使用measureText()测量整个字符串的宽度

  3. 从字符串中删除第一个字符

  4. 使用fillText()打印位置(X,Y)处的第一个字符

  5. 测量wShorter,使用measureText()得到的较短字符串的宽度。

  6. 从整个字符串的宽度中减去较短字符串的宽度,给出字符的宽度, wChar = wAll - wShorter

  7. 以wChar +间距增加X

  8. wAll = wShorter

  9. 3

  1. Start at position (X, Y).
  2. Measure wAll, the width of the entire string using measureText()
  3. Remove the first character from the string
  4. Print the first character at position (X, Y) using fillText()
  5. Measure wShorter, the width of the resulting shorter string using measureText().
  6. Subtract the width of the shorter string from the width of the entire string, giving the kerned width of the character, wChar = wAll - wShorter
  7. Increment X by wChar + spacing
  8. wAll = wShorter
  9. Repeat from step 3

这不会考虑字距调整吗?我缺少什么? measureText()添加一个填充的负载,这取决于最外面的字符,或某事,如果这样,不会fillText()使用相同的系统输出字符,否定的问题?上面的链接中有人提到像素对齐字体提示,但我不认为这是如何适用这里。任何人都可以一般性地或具体地提出,如果这将工作,或者有问题吗?

Would this not take into account kerning? Am I missing something? Does measureText() add a load of padding that varies depending on the outermost character, or something, and if it does, would not fillText() use the same system to output the character, negating that issue? Someone in the link above mentioned 'pixel-aligned font hinting' but I don't see how that applies here. Can anyone advise either generally or specifically if this will work or if there are problems with it?

推荐答案

代码,基于上面的伪代码,并通过截断和眼睛化其差异(缩放,使用来自例如剪辑框的直线来比较每个字符的X位置和宽度)进行几个比较。看起来完全一样,间距设置为0。

Well, I've written the code, based on the pseudocode above, and done a few comparisons by screenshotting and eyeballing it for differences (zoomed, using straight lines from eg clip boxes to compare X position and width for each character). Looks exactly the same for me, with spacing set at 0.

这里是HTML:

<canvas id="Test1" width="800px" height="200px"><p>Your browser does not support canvas.</p></canvas>

以下是代码:

this.fillTextWithSpacing = function(context, text, x, y, spacing)
{
    //Start at position (X, Y).
    //Measure wAll, the width of the entire string using measureText()
    wAll = context.measureText(text).width;

    do
    {
    //Remove the first character from the string
    char = text.substr(0, 1);
    text = text.substr(1);

    //Print the first character at position (X, Y) using fillText()
    context.fillText(char, x, y);

    //Measure wShorter, the width of the resulting shorter string using measureText().
    if (text == "")
        wShorter = 0;
    else
        wShorter = context.measureText(text).width;

    //Subtract the width of the shorter string from the width of the entire string, giving the kerned width of the character, wChar = wAll - wShorter
    wChar = wAll - wShorter;

    //Increment X by wChar + spacing
    x += wChar + spacing;

    //wAll = wShorter
    wAll = wShorter;

    //Repeat from step 3
    } while (text != "");
}

演示/眼球测试代码:

element1 = document.getElementById("Test1");
textContext1 = element1.getContext('2d');

textContext1.font = "72px Verdana, sans-serif";
textContext1.textAlign = "left";
textContext1.textBaseline = "top";
textContext1.fillStyle = "#000000";

text = "Welcome to go WAVE";
this.fillTextWithSpacing(textContext1, text, 0, 0, 0);
textContext1.fillText(text, 0, 100);

理想情况下,我会在它上面引入多个随机字符串,并进行逐像素比较。我也不知道Verdana的默认字距是多好,虽然我知道它比Arial更好 - 对其他字体的建议尝试接受。

Ideally I'd throw multiple random strings at it and do a pixel by pixel comparison. I'm also not sure how good Verdana's default kerning is, though I understand it's better than Arial - suggestions on other fonts to try gratefully accepted.

所以...远远看起来不错。事实上它看起来完美。
仍然希望有人会指出过程中的任何缺陷。

So... so far it looks good. In fact it looks perfect. Still hoping that someone will point out any flaws in the process.

在此期间,我会把这里给别人看看他们是否在寻找解决方案。

In the meantime I will put this here for others to see if they are looking for a solution on this.

这篇关于在HTML画布中添加字母间距的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆