gpt4 book ai didi

javascript - Chrome canvas 2d context measureText 给我奇怪的结果

转载 作者:太空狗 更新时间:2023-10-29 13:47:58 26 4
gpt4 key购买 nike

这是我的问题的精简版

let canvas = document.createElement('canvas')
let ctx = canvas.getContext('2d')
ctx.font = '11pt Calibri'
ctx.fillStyle = '#000000'
let temp = ctx.font
console.log(ctx.font)
console.log(ctx.measureText('M').width)
ctx.font = 'bold ' + ctx.font
console.log(ctx.font)
console.log(ctx.measureText('M').width)
ctx.font = 'italic ' + ctx.font
console.log(ctx.font)
console.log(ctx.measureText('M').width)
ctx.font = temp
console.log(ctx.font)
console.log(ctx.measureText('M').width)

在 chrome 中运行这段代码会产生不正确的数字,至少在最后是这样。首先,我将字体设置为“11pt Calibri”,但 chrome 出于某种原因立即将其更改为“15px Calibri”,因此它生成的文本比正确的稍大。我读到 Canvas 以 96dpi 运行,所以正确的 px 应该是 14.6。

之后,我正在测量文本 M 的宽度,结果对我来说是 12.53401184,这个数字很重要。

之后,我修改了字体以添加粗体和斜体,然后将其恢复为原来的字体。现在当我测量它时,它给了我 12.824707,这是一个巨大的 0.3px 关闭。我在宽度从 600px 到 800px 的 Canvas 上绘制文本,我需要它正确换行,所以我需要它精确到线上 1px,所以单个字母需要至少有 0.02px 的精度,这在我开始使用粗体和斜体之前工作得很好。

以上问题在firefox上都不存在,在chrome上禁用canvas硬件加速好像也没什么效果。我使用的是当前最新版本的 chrome 52.0。

编辑:我发现你甚至不需要做任何事情来获得不正确的数字,只需这样做就足够了。

let canvas = document.createElement('canvas')
let ctx = canvas.getContext('2d')
ctx.font = '11pt Calibri'
ctx.fillStyle = '#000000'

console.log(ctx.font)
console.log(ctx.measureText('M').width)
let temp = ctx.font
ctx.font = temp
console.log(ctx.font)
console.log(ctx.measureText('M').width)

最佳答案

不要使用“pt”来调整 Canvas 上的字体大小。

CSS 绝对单位和魔法单位

使用 pt 调整字体大小是 not recommended因为它对于以像素(离散不可分割的图像单元)表示视觉信息的媒体没有实际意义,并且显示在没有固定像素密度的屏幕上。

pt是一个绝对测量单位,与cm相同,而px是一个“魔法单位”,只有绝对值当媒体类型为打印时。

OP: "I read that the canvas runs at 96dpi so the correct px should be 14.6."

这是不正确的,因为 Canvas 没有绝对测量单位。当打印媒体类型时,作为 CSS 单位的像素仅具有绝对尺寸,在这种情况下 1px = 1/96 英寸。 Canvas 不被视为打印媒体。


为什么宽度会改变?

明显的问题

ctx.font = '11pt Calibri'
console.log(ctx.font); // 15px Calibri
console.log(ctx.measureText('M').width); // 12.534011840820312
ctx.font = ctx.font
console.log(ctx.font); // 15px Calibri
console.log(ctx.measureText('M').width); // 12.82470703125

虽然 ctx.font 值相同,但测量的字体宽度不同

简单的解决方案

ctx.font = ctx.font = '11pt Calibri';

将避免测量的大小差异,但我相信没有人会认为这是对“明显的”浏览器特定错误的丑陋解决方法。

解决方案

设置 Canvas 字体时不要使用pt单位。

发生了什么。

这个问题是对 ctx.font 属性的误解。它不代表当前字体的实际内部表示,而是一种抽象的人类可读形式。

W3C 2D Canvas: "On getting, the font attribute must return the serialized form of the current font of the context."

序列化的过程会失去精度。 Serialising CSS values .W3C 标准指定 font-sizepx 为单位,在这种情况下进一步放大了明显的“错误”

font 属性设置函数获取 CSS 字体字符串,对其进行解析。如果有效,则设置 Canvas 内部字体并将序列化的 CSS 字体值写入 context.font 两者不必匹配,标准也没有指定它们应该匹配。


总结

问题中描述的行为不是“错误”。浏览器之间的不一致(一如既往)是一个问题。如果我们要遵循标准,可以认为浏览器没有显示测量不一致错误地解释了标准并用他们自己的解释填充了歧义(尽管这对我来说是推测性的)。

该问题的简单解决方案是遵循标准的指导方针,并且在为打印媒体以外的任何内容设置 font-size 值时不使用 pt

与所有计算机媒体一样,“dpi”只有在打印时才有意义,直到那时才被定义。打印时像素也不一定等同于点。在提及像素而不是 dp1(我最讨厌)

时始终使用分辨率

关于javascript - Chrome canvas 2d context measureText 给我奇怪的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38823353/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com