Javascript canvas元素中的字母间距

Javascript canvas元素中的字母间距,javascript,css,html,canvas,letter-spacing,Javascript,Css,Html,Canvas,Letter Spacing,这个问题几乎说明了这一切。我一直在四处寻找,开始担心这是不可能的 我有一个画布元素,我正在绘制文本。我想设置与CSS字母间距属性类似的字母间距。我的意思是在绘制字符串时增加字母之间的像素数量 我绘制文本的代码是这样的,ctx是canvas上下文变量 ctx.font = "3em sheepsans"; ctx.textBaseline = "middle"; ctx.textAlign = "center"; ctx.fillStyle = "rgb(255, 255, 255)"; ctx.

这个问题几乎说明了这一切。我一直在四处寻找,开始担心这是不可能的

我有一个画布元素,我正在绘制文本。我想设置与CSS
字母间距
属性类似的字母间距。我的意思是在绘制字符串时增加字母之间的像素数量

我绘制文本的代码是这样的,ctx是canvas上下文变量

ctx.font = "3em sheepsans";
ctx.textBaseline = "middle";
ctx.textAlign = "center";
ctx.fillStyle = "rgb(255, 255, 255)";
ctx.fillText("Blah blah text", 1024 / 2, 768 / 2);

我尝试添加
ctx.letterspating=“2px”在绘图之前,但无效。有没有一种方法可以通过简单的设置来实现这一点,或者我必须创建一个函数来单独绘制每个字符,并记住间距?

您不能将字母间距设置为画布上下文的属性。您只能通过手动间距来实现效果,抱歉。(如中所示,手动绘制每个字母,将每个字母上的x增加一些像素量)

对于记录,可以使用
ctx.font
设置一些文本属性,但字母间距不是其中之一。您可以设置的有:“字体样式字体变量字体重量字体大小/行高字体系列”

例如,从技术上讲,您可以编写
ctx.font=“bold normal normal 12px/normal Verdana”
(或其中任何一项的任何省略),它将正确解析。

我不确定它是否可以工作(根据规格),但在某些浏览器(Chrome)中,您可以在
元素本身上设置
字母间距
CSS属性,它将应用于在上下文中绘制的所有文本。(适用于Chrome v56,不适用于Firefox v51或IE v11。)

请注意,在Chrome v56中,每次更改
字母间距
样式后,必须重新获取画布2d上下文(并重新设置您关心的任何值);间距似乎已烘焙到您获得的二维上下文中

例子:
var inp=document.querySelectorAll('input'),
can=document.querySelector('canvas'),
ctx=can.getContext('2d');
can.width=can.offsetWidth;
[]forEach.call(inp,函数(inp){inp.addEventListener('input',redraw,false)});
重画();
函数重画(){
ctx.clearRect(0,0,罐宽,罐高);
can.style.letterSpacing=inp[0]。值+'px';
ctx=can.getContext('2d');
ctx.textAlign='中心';
ctx.textb基线='中间';
ctx.font='4em sans serif';
ctx.fillText('Hello',can.width/2,can.height*1/4);
can.style.letterSpacing=inp[1]。值+'px';
ctx=can.getContext('2d');
ctx.textAlign='中心';
ctx.textb基线='中间';
ctx.font='4em sans serif';
ctx.fillText('World',can.WITH/2,can.height*3/4);
};
canvas{背景:白色}
画布,标签{显示:块;宽度:400px;边距:0.5em自动}

您好间距:

世界间距:
您不能设置字母间距属性,但可以通过在字符串中的每个字母之间插入一个不同的空格,在画布中实现更宽的字母间距。比如说

ctx.font = "3em sheepsans";
ctx.textBaseline = "middle";
ctx.textAlign = "center";
ctx.fillStyle = "rgb(255, 255, 255)";
var ctext = "Blah blah text".split("").join(String.fromCharCode(8202))
ctx.fillText(ctext, 1024 / 2, 768 / 2);
这将在每个字母之间插入一个字母

使用8201(而不是8202)将插入稍宽的

有关更多空白选项,请参见


与手动定位每个字母相比,此方法将帮助您更容易地保留字体的字距,但是您无法以这种方式收紧字母间距

这里有一些咖啡脚本,可以让你像这样设置上下文的字距

tctx = tcanv.getContext('2d')
tctx.kerning = 10
tctx.fillStyle = 'black'
tctx.fillText 'Hello World!', 10, 10
支持代码为:

_fillText = CanvasRenderingContext2D::fillText
CanvasRenderingContext2D::fillText = (str, x, y, args...) ->

  # no kerning? default behavior
  return _fillText.apply this, arguments unless @kerning?

  # we need to remember some stuff as we loop
  offset = 0

  _.each str, (letter) =>

    _fillText.apply this, [
      letter
      x + offset + @kerning
      y
    ].concat args # in case any additional args get sent to fillText at any time

    offset += @measureText(letter).width + @kerning
javascript将是

var _fillText,
  __slice = [].slice;

_fillText = CanvasRenderingContext2D.prototype.fillText;

CanvasRenderingContext2D.prototype.fillText = function() {
  var args, offset, str, x, y,
    _this = this;

  str = arguments[0], x = arguments[1], y = arguments[2], args = 4 <= arguments.length ? __slice.call(arguments, 3) : [];
  if (this.kerning == null) {
    return _fillText.apply(this, arguments);
  }
  offset = 0;

  return _.each(str, function(letter) {
    _fillText.apply(_this, [letter, x + offset + _this.kerning, y].concat(args));
    offset += _this.measureText(letter).width + _this.kerning;
  });
};
var\u fillText,
__切片=[].slice;
_fillText=CanvasRenderingContext2D.prototype.fillText;
CanvasRenderingContext2D.prototype.fillText=函数(){
变量args,偏移量,str,x,y,
_这个=这个;

str=arguments[0]、x=arguments[1]、y=arguments[2]、args=4为了考虑“字母紧排对”之类的问题,我写了以下内容。应该考虑到这一点,粗略的测试表明确实如此。如果您对此有任何意见,那么我将向您指出我关于这个主题的问题()

基本上,它使用measureText()获得整个字符串的宽度,然后删除字符串的第一个字符并测量剩余字符串的宽度,并使用差分计算正确的定位,从而考虑紧排对等。有关更多伪代码,请参阅给定的链接

以下是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好——关于其他字体的建议,请尝试接受

到目前为止,它看起来不错。事实上,它看起来很完美。 仍然希望有人能指出这个过程中的任何缺陷

同时,我将把这个放在这里,让其他人看看他们是否在寻找解决方案。

我使用:

ctx.font = "32px Tahoma";//set font
ctx.scale(0.75,1);//important! the scale
ctx.fillText("LaFeteParFete test text", 2, 274);//draw
ctx.setTransform(1,0,0,1,0,0);//reset transform

不正确。您可以在css中将字母间距属性添加到画布元素中,效果非常好。不需要复杂的解决方法。我刚刚在画布项目中找到了它。例如: 帆布{ 宽度:480px; 高度:350px; 利润率:30px自动0; 填充:15px0; 背景:粉红色; 显示:块; 边框:2件棕色虚线; 字母间距:0.1米;
}实际上,字母间距概念画布不支持

所以我用javascript来做这件事

var value = $('#sourceText1').val().split("").join(" "); var value=$('#sourceText1').val().split(“”).join(“”); 或

var sample_text=“Praveen chelumala”;
var text=sample_text.split(“”).join(“”;支持画布中的字母间距,我使用了

canvas = document.getElementById('canvas');
canvas.style.letterSpacing = '2px';

我不知道其他人的情况,但我已经通过增加我正在写的文本上的y值来调整行距。我实际上是在按空格分割字符串,并在循环中将每个单词向下踢一行。我使用的数字基于默认字体。如果使用不同的字体,这些数字将 var sample_text = "Praveen Chelumalla"; var text = sample_text.split("").join(" ");
canvas = document.getElementById('canvas');
canvas.style.letterSpacing = '2px';
// object holding x and y coordinates
var vectors = {'x':{1:100, 2:200}, 'y':{1:0, 2:100}
// replace the first letter of a word
var newtext = YOURSTRING.replace(/^\b[a-z]/g, function(oldtext) {
    // return it uppercase
    return oldtext.toUpperCase(); 
});
// split string by spaces
newtext = newtext.split(/\s+/);

// line height
var spacing = 10 ;
// initial adjustment to position
var spaceToAdd = 5;
// for each word in the string draw it based on the coordinates + spacing
for (var c = 0; c < newtext.length; c++) {
    ctx.fillText(newtext[c], vectors.x[i], vectors.y[i] - spaceToAdd);
    // increment the spacing 
    spaceToAdd += spacing;
}               
export function fillTextWithSpacing(context, text, x, y, spacing, textAlign) {
    const totalWidth = context.measureText(text).width + spacing * (text.length - 1);
    switch (textAlign) {
        case "right":
            x -= totalWidth;
            break;
        case "center":
            x -= totalWidth / 2;
            break;
    }
    for (let i = 0; i < text.length; i++) {
        let char = text.charAt(i);
        context.fillText(char, x, y);
        x += context.measureText(char).width + spacing;
    }
}