【发布时间】:2016-12-13 21:11:48
【问题描述】:
这是我的问题的精简版
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”,因此它产生的文本略大于正确。我读到画布以 96dpi 运行,所以正确的 px 应该是 14.6。
在那之后,我测量了文本 M 的宽度,对我来说是 12.53401184,这个数字很重要。
之后,我修改了字体以添加粗体和斜体,然后将其回滚到原来的字体。现在当我测量它时,它给了我 12.824707,这是一个巨大的 0.3 像素。我在画布上绘制文本,宽度从 600 像素到 800 像素不等,我需要它正确换行,所以我需要它在线条上精确到 1 像素,所以单个字母需要至少有 0.02 像素的精度,这在我开始使用粗体和斜体之前工作得很好。
上述问题在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)
【问题讨论】:
-
好吧,我认为您已经准备好向 chrome 提交错误报告。他们正在将字体大小单位即时转换为
px而他们不应该这样做,并且由于他们不为此px单位使用浮动值,因此会产生此问题,但您已经知道了。跨度> -
好的,我会这样做,只是想确保我没有遗漏一些明显的东西。
-
不,我认为这是一个糟糕的实现,在 FF 中,它们也允许
px单元的浮动值。 -
以防万一——一个可能的解决方法是尝试使用普通的 HTML 跨度来测量文本。只需将其绝对定位,根据需要设置
visibility: hidden和font样式属性,将contentText属性设置为文本值进行测量,然后调用span.getBoundingClientRect().width,它似乎在Chrome中给出了准确的浮点像素值。 -
好的,我提交了错误报告。还有安德鲁,我是否需要将跨度添加到 DOM 才能正常工作? bugs.chromium.org/p/chromium/issues/detail?id=635427
标签: javascript html google-chrome canvas