在HTML画布中添加字母间距
我已经阅读了很多关于如何在画布上设置字母间距的StackOverflow答案和其他页面。其中一个更有用的是 正如另一个问题所说,“我有一个画布元素,我正在绘制文本。我想设置类似于CSS字母间距属性的字母间距。我的意思是在绘制字符串时增加字母之间的像素量。请注意,字母间距有时被错误地称为紧排 我注意到,一般的方法似乎是逐字母输出字符串,使用measureText(字母)获得字母的宽度,然后添加额外的间距。问题是它没有考虑字母紧排对等。请参阅上面的链接以获取此示例和相关注释 在我看来,对于“间距”的行距,这样做的方法是:在HTML画布中添加字母间距,html,canvas,text,fonts,Html,Canvas,Text,Fonts,我已经阅读了很多关于如何在画布上设置字母间距的StackOverflow答案和其他页面。其中一个更有用的是 正如另一个问题所说,“我有一个画布元素,我正在绘制文本。我想设置类似于CSS字母间距属性的字母间距。我的意思是在绘制字符串时增加字母之间的像素量。请注意,字母间距有时被错误地称为紧排 我注意到,一般的方法似乎是逐字母输出字符串,使用measureText(字母)获得字母的宽度,然后添加额外的间距。问题是它没有考虑字母紧排对等。请参阅上面的链接以获取此示例和相关注释 在我看来,对于“间距”的
编辑:这不是另一个问题的副本-它链接到并引用了该问题。问题不在于如何根据提议的副本“在画布上设置字母间距”;这是针对该问题和其他问题提出一个可能的解决方案(据我所知,没有其他人提出),并询问是否有人能看到或知道该拟议解决方案的任何问题,即询问拟议解决方案及其要点,包括measureText()和fillText()的详细信息和“像素对齐字体提示”。好吧,我已经根据上面的伪代码编写了代码,并通过截屏和目测差异(缩放,使用例如剪辑框中的直线来比较每个字符的X位置和宽度)进行了一些比较。对我来说看起来完全一样,间距设置为0 以下是HTML:
<canvas id="Test1" width="800px" height="200px"><p>Your browser does not support canvas.</p></canvas>
演示/眼球测试代码:
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好——关于其他字体的建议值得尝试
所以。。。到目前为止看起来不错。事实上,它看起来很完美。
仍然希望有人能指出这个过程中的任何缺陷
同时,我会把这个放在这里,让其他人看看他们是否在寻找解决方案。我的答案被删除了。
所以,我使用的是chrome,这是我的完整代码
second_image = $('#block_id').first();
canvas = document.getElementById('canvas');
canvas.style.letterSpacing = '2px';
ctx = canvas.getContext('2d');
canvas.crossOrigin = "Anonymous";
canvasDraw = function(text, font_size, font_style, fill_or_stroke){
canvas.width = second_image.width();
canvas.height = second_image.height();
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.drawImage(second_image.get(0), 0, 0, canvas.width, canvas.height);
//refill text
ctx.font = font_size +'px '+ font_style + ',Symbola';
$test = ctx.font;
ctx.textAlign = "center";
if(fill_or_stroke){
ctx.fillStyle = "#d2b76d";
ctx.strokeStyle = "#9d8a5e";
ctx.strokeText(text,canvas.width*$left,canvas.height*$top);
ctx.fillText(text,canvas.width*$left,canvas.height*$top);
}
else{
ctx.strokeStyle = "#888888";
ctx.strokeText(text,canvas.width*$left,canvas.height*$top);
}
};
而且您不需要使用此函数
this.filltextwithspace
。我没有使用,它就像一个符咒一样工作)我已经做了一些初步测试,它看起来很有效。。。但我还没有做过详尽的测试。你的问题不清楚你想要实现什么?如果你想让字母在[x,y]上居中,你可以这样做:context.textAlign='center'
在x上水平居中,context.textb基线='middle'
在y上垂直居中,context.fillText('a',x,y)
在[x,y]上画一个居中的字母。请分享一些代码…@markE,我希望现在更清楚。抱歉我无意中将你的评论标记为有用,因为它与我所追求的内容无关,但你关于它的不清楚的评论至少让我澄清了它,所以谢谢。@bvl-我给出伪代码的原因是因为我没有代码,我希望除非它有用,否则不要写它。尽管如此,在等待答案的过程中,我继续写下了代码,你可以在下面的答案中看到。应该注意的是,虽然这并不是对我问题的回答,但它回答了很多关于如何做到这一点的问题,它就是为了这个目的而存在的。如果有人回答了我的问题,解释为什么它不是一个好的系统,那么这个答案显然会取代我的答案。这个解决方案的一个缺点是它的复杂性为O(n^2),因为measureText在字符串中的其余字符上循环,并且每个字符只调用一次。似乎很容易将其转换为只考虑当前字符和下一个字符,从而将其转换为O(n)算法。除此之外,非常好的解决方案@Joaquincuencabela-我同意,出于你给出的理由,这可能是过分的。我就这样离开了,因为我不确定是否根据整个字符串(而不是成对的字符)添加了某种“魔法酱”,但我怀疑您的添加结果会完全相同,如果没有,一行至少三个字符或整个单词可能就够了。欢迎任何人测试-请发回。两点-1。此解决方案适用于大多数拉丁语脚本(英语、法语等),但对于来自非拉丁语脚本(如婆罗米语、阿拉伯语、希伯来语等)的字符,会给出错误的结果。2。此解决方案可以稍加修改,以使用表情符号给出正确的结果。您好@NirmitDalal,您能详细介绍一下您对表情符号的修改建议吗?
second_image = $('#block_id').first();
canvas = document.getElementById('canvas');
canvas.style.letterSpacing = '2px';
ctx = canvas.getContext('2d');
canvas.crossOrigin = "Anonymous";
canvasDraw = function(text, font_size, font_style, fill_or_stroke){
canvas.width = second_image.width();
canvas.height = second_image.height();
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.drawImage(second_image.get(0), 0, 0, canvas.width, canvas.height);
//refill text
ctx.font = font_size +'px '+ font_style + ',Symbola';
$test = ctx.font;
ctx.textAlign = "center";
if(fill_or_stroke){
ctx.fillStyle = "#d2b76d";
ctx.strokeStyle = "#9d8a5e";
ctx.strokeText(text,canvas.width*$left,canvas.height*$top);
ctx.fillText(text,canvas.width*$left,canvas.height*$top);
}
else{
ctx.strokeStyle = "#888888";
ctx.strokeText(text,canvas.width*$left,canvas.height*$top);
}
};