Letter spacing in canvas element

2019-02-02 21:02发布

The question says it all pretty much. I've been searching around and starting to worry that it's impossible.

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.

My code for drawing the text is like so, ctx is the canvas context variable.

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);

I've tried adding ctx.letterSpacing = "2px"; before the drawing but with no avail. Is there a way to do this just with a simple setting, or will I have to make a function to individually draw each character with the spacing in mind?

9条回答
何必那么认真
2楼-- · 2019-02-02 21:29

here's some coffeescript that allows you to set kerning to your context like so

tctx = tcanv.getContext('2d')
tctx.kerning = 10
tctx.fillStyle = 'black'
tctx.fillText 'Hello World!', 10, 10

the supporting code is:

_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

The javascript would be

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;
  });
};
查看更多
The star\"
3楼-- · 2019-02-02 21:30

I use:

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
查看更多
神经病院院长
4楼-- · 2019-02-02 21:31

You can't set the letter spacing property, but you you can accomplish wider letter spacing in canvas by inserting one of the various white spaces in between every letter in the string. For instance

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);

This will insert a hair space between every letter.

Using 8201 (instead of 8202) will insert the slightly wider thin space

For more white space options, see this list of Unicode Spaces

This method will help you to preserve the font's kerning much more easily than manually positioning each letter, however you wont be able to tighten your letter spacing this way.

查看更多
登录 后发表回答