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 字体来避免它,但这仍然不是防弹的,因为即使那样一些字形也不能像你那样测量。
所以最好是测量你想测量的全文。
在大多数情况下,它们是相同的。但是我发现了这种特殊情况,当我改变字符顺序时就不一样了。
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 字体来避免它,但这仍然不是防弹的,因为即使那样一些字形也不能像你那样测量。
所以最好是测量你想测量的全文。