首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么每个项的和宽度不等于画布文本度量中的总和。

为什么每个项的和宽度不等于画布文本度量中的总和。
EN

Stack Overflow用户
提问于 2021-03-09 14:30:13
回答 1查看 69关注 0票数 1

字符1的宽度为8.8984375。

所以我认为10个字符的宽度是88.984375,但实际上是78.296875。

代码语言:javascript
复制
let canvas = document.querySelector('#canvas');
let ctx = canvas.getContext('2d');
ctx.font = '16px/16px arial';
let per = ctx.measureText('1').width;
let num = 10;
let total = ctx.measureText('1111111111').width;
console.log(per, total, per * 10);
代码语言:javascript
复制
<canvas id="canvas"></canvas>

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-03-09 17:34:38

文本度量是复杂的,特别是当字体不是单一间距时。一些字符在自己测量时会被填充。当使用1时,"arial"恰好是其中之一

计算填充物。

假设

  • 在其自身旁边的字符(两边)将占用每个

相同的宽度

  • 两端相同字符的字符串将具有相同的填充。

计算

对于"1“字,我们可以通过测量"111”和"11111“两种情况来计算大致的填充量。然后,我们可以创建一个表达式来定义字符宽度w和填充p

因此对弦乐来说..。

  • "111“宽度为w * 3 + p = w3

w * 5 + p = w5.

  • "11111“宽度为

我们现在有两个含有2个未知数的方程,因为我们可以使用w3w5得到measureText

求解p(填充) p = (15 * (w3 / 3) - (3 * w5)) / 2,则w(字符宽度)为w = (w3 - p) / 3

示例

该示例计算1到1到~100像素宽度之间的宽度1。

代码语言:javascript
复制
const width = str => ctx.measureText(str).width;
const test = (str, calc) => 
    console.log("'" + str + "' width = " + width(str).toFixed(2) + 
                "px, calculated = " + calc.toFixed(2) + 
                "px, dif = " + (calc - width(str)).toFixed(2) + "px");


const ctx = canvas.getContext("2d");
ctx.font = '16px arial';
const c = "1";

// calculate padding and width of 1
const w3 = width(c.padStart(3, c));
const w5 = width(c.padStart(5, c));    
const padding = (15 * (w3 / 3) -  3 * w5) / 2;
const w = (w3 - padding) / 3;

// test result
test(c, w + padding);
test(c.padStart(10, c), w * 10 + padding);
test(c.padStart(20, c), w * 20 + padding);

console.log("Width of '"+c+"' is ~" + w.toFixed(2) + "px");
console.log("Padding is ~" + padding.toFixed(2) + "px");
代码语言:javascript
复制
<canvas id="canvas"></canvas>

其他字符

不是所有字符都有填充,下面的示例计算数字和小写字母的填充。

代码语言:javascript
复制
const width = str => ctx.measureText(str).width;
const test = (str, calc) => 
    console.log("'" + str + "' width = " + width(str).toFixed(2) + 
                "px, calculated = " + calc.toFixed(2) + 
                "px, dif = " + (calc - width(str)).toFixed(2) + "px");


const ctx = canvas.getContext("2d");
ctx.font = '16px arial';
console.log("Font: " + ctx.font);
[..."1234567890abcdefghijklmnopqrstuvwxyz"].forEach(calcWidthFor);

function calcWidthFor(c) {
    const w3 = width(c.padStart(3, c));
    const padding = (15 * (w3 / 3) - (3 * width(c.padStart(5, c)))) / 2;
    const w = (w3 - padding) / 3;
    console.log("Width of '"+c+"' is ~ " + w.toFixed(2) + "px Padding is ~ " + padding.toFixed(2) + "px");
}
代码语言:javascript
复制
<canvas id="canvas"></canvas>

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66548845

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档