从 canvas.measureText 中获取包含元素的预期渲染大小?

Get the expected rendered size of containing element from canvas.measureText?

提问人:Leo 提问时间:11/17/2023 最后编辑:ggorlenLeo 更新时间:11/19/2023 访问量:54

问:

在将 DOM 元素 () 附加到文档之前,我获取 DOM 元素 () 中文本的 TextMetrics,如下所示:position: absolut/fixed; display: block;

function getTextMetrics(txt, font) {
    const canvas = document.createElement("canvas");
    const context = canvas.getContext("2d");
    context.font = font;
    const tm = context.measureText(txt);
    return tm;
} 

看着我不明白我是如何得到渲染的高度/宽度的。似乎缺少一些东西。什么?tm

是的,返回的 TextMetric 中有一些字段几乎适合,但它们不等于后面呈现的元素的 .clientWidth/Height。

没有必要为此创建一个“工作示例”。这太简单了。以下是一些数字(来自 Google Chrome,@ggorlen提到的值不存在):

   .clientWidth: 82
   .clientHeight: 20

   tm:
   width : 73.2734375
   fontBoundingBoxAscent : 16
   fontBoundingBoxDescent : 3
javascript google-chrome html5-canvas 渲染

评论

1赞 ggorlen 11/17/2023
你到底想实现什么?查看 TextMetrics,有一个 和 /。我不确定你期望在那里做什么,你认为不是。“渲染”的高度/宽度与高度/宽度相比是什么意思?.width.emHeightAscent.emHeightDescent
2赞 Sharp Dev 11/17/2023
我不太明白你的问题。tm 应该包含文本的宽度,高度可以通过多种方式确定......我真的不明白你的问题,你提到你正在附加一个 DOM 元素......在渲染元素之前需要大小是否有特殊原因?
0赞 Leo 11/17/2023
@SharpDev 渲染是异步的。布局需要尺寸。(这是一个思维导图。
1赞 Sharp Dev 11/17/2023
根据我的理解,您的语句@Leo您想要一种方法在呈现主要内容之前同步获取呈现的宽度和高度。如果是这种情况,那么您不需要canvas.measureText(我会避免它)...如果我以另一种方式利用 DOM 解决您的问题可以吗?
1赞 ggorlen 11/17/2023
".clientWidth的元素只包含文本“--这个元素在哪里?如果它应用了CSS,也许这解释了差异?什么浏览器?

答:

0赞 Helder Sepulveda 11/19/2023 #1

这是我过去使用过的东西:

    tm = context.measureText(txt); // width is obvious "tm.width" 
    h = tm.actualBoundingBoxAscent + tm.actualBoundingBoxDescent

...需要明确的是,这些值适用于该特定画布中的文本,这些值与画布外的其他元素没有直接关系。
从文档中:
https://developer.mozilla.org/en-US/docs/Web/API/TextMetrics

TextMetrics 接口表示画布中一段文本的尺寸;可以使用 CanvasRenderingContext2D.measureText() 方法检索 TextMetrics 实例。

试试下面的代码,看看这是否能让你更接近你的目标。

function fillText(ctx, x, y, txt, font) {
    ctx.font = font;
    ctx.fillText(txt, x, y)
    const tm = ctx.measureText(txt);
    const h = tm.actualBoundingBoxAscent + tm.actualBoundingBoxDescent
    ctx.rect(x, y, tm.width, -h); 
    ctx.stroke();
    return tm;
} 

const canvas = document.getElementById("x");
const context = canvas.getContext("2d");
context.strokeStyle = "red";

x = fillText(context, 10, 30, "HELLO", "20px monospace")
//console.log(x)
x = fillText(context, 10, 85, "WORLD", "60px monospace")
//console.log(x)
x = fillText(context, 120, 35, "123.456-7890", "40px monospace")
//console.log(x)
<canvas id="x" width=600></canvas>

在此代码中,我使用从 measureText 获得的值绘制了一些文本和一个矩形,如下所示,这些值正确匹配