Canvas: 文本宽度不等于其字符宽度的汇总

Canvas: Text width is not equal to the summary of the widths of its characters

在大多数情况下,它们是相同的。但是我发现了这种特殊情况,当我改变字符顺序时就不一样了。

const ctx = document.createElement('canvas').getContext('2d');
const tw = text => ctx.measureText(text).width;

tw('Tr') - tw('T') - tw('r') // -0.3662109375
tw('rT') - tw('T') - tw('r') // 0

谁能告诉我这种行为的规则?谢谢!

这是因为 kerning,这就是一些角色或多或少会靠近他们的邻居的方式。 这将取决于使用的字体和显示的字符。

Chrome 最近添加了对 .fontKerning 属性 的支持,我们可以使用它来禁用它,

if ("fontKerning" in CanvasRenderingContext2D.prototype) {
  const canvas = document.querySelector("canvas");
  const ctx = canvas.getContext("2d");
  ctx.textBaseline = "middle";
  ctx.font = "30px sans-serif";
  ctx.fillText("AV", 0, 30);
  console.log("with kerning", ctx.measureText("AV").width);
  ctx.fontKerning = "none";
  console.log("without kerning", ctx.measureText("AV").width);
  ctx.fillText("AV", 0, 60);
  console.log("sum of chars", ctx.measureText("A").width + ctx.measureText("V").width);
}
else {
  console.log("your browser doesn't support setting fontKerning");
}
<canvas></canvas>

你可以使用 mono-space 字体来避免它,但这仍然不是防弹的,因为即使那样一些字形也不能像你那样测量。

所以最好是测量你想测量的全文。