Fuz*_*yma 1 javascript fonts svg bounding-box
在浏览器中使用 SVG 时,浏览器具有getBBox为您提供各种元素的边界框的功能。但是当涉及到文本元素时,我真的很困惑这个边界框是如何计算的。我知道 fontsize 是基于字体文件中指定的 em-Box 的。然而我的测试表明,这些都不会产生与 FF 或 Chrome 相同的结果(在 fontsize 1000 上仅相差几个像素):
fontSize != bbox-height
(ascender-descender)/unitsPerEm * fontSize != bbox-height
(unitsPerEm-descender)/unitsPerEm * fontSize != bbox-height
...maybe adding a fixed amount to ascender for accents? Like ?
Run Code Online (Sandbox Code Playgroud)
那么浏览器中文本的 bbox 高度背后的秘密是什么呢?
我什至尝试查看 FF 和 Chrome 的源代码,但找到计算所基于的正确位置本身就是一个挑战
// 编辑:响应评论:我想计算 svg 文本的 bbox,就像在浏览器中所做的那样(复制行为)。我需要知道正确计算 bbox 所需的字体度量以及用于计算的公式(宽度和高度就足够了)
经过大量的研究和反复试验,我找到了一个可能的解决方案,至少可以解释文本 bbox 尺寸的 chromes 行为。
首先我使用 npm 包fontkit来加载和解析字体文件。
fontkit为您提供整体字体的几个指标,其中包括:
所以为了计算 bbox 的高度,我想出了以下内容:
bboxHeight = (font.ascent - font.descent + font.lineGap) / unitsPerEm * fontSize
Run Code Online (Sandbox Code Playgroud)
但是,当字体大于 em 框 ( font.ascent - font.descent > unitsPerEm)时,这会导致错误。在这种特殊情况下bboxHeight是font.ascent - font.descent。
这导致以下高度代码:
var fontHeight = font.ascent - font.descent
var lineHeight = fontHeight > font.unitsPerEm ? fontHeight : fontHeight + font.lineGap
var height = lineHeight/font.unitsPerEm * fontSize
Run Code Online (Sandbox Code Playgroud)
计算文本的宽度我利用layout了fontkit. layout使您可以访问绘制文本的字形,还可以访问字形的度量。我们需要的指标是advanceWidth包含当前 glpyh 旁边其他字形的边距。通过总结所有advanceWidths 并相应地缩放它们,我最终得到了bboxWidth:
var width = font.layout(text).glyphs.reduce((last, curr) => last + curr.advanceWidth, 0)
width = width / font.unitsPerEm * fontSize
Run Code Online (Sandbox Code Playgroud)
麻烦还不止这些,我们还要计算bbox的y位置。这是一个相当简单的公式:
var bboxY = y-font.ascent/font.unitsPerEm * fontSize
Run Code Online (Sandbox Code Playgroud)
其中 y 是您将从 dom(y和dy属性)中拉出的理论位置
那只是你从 dom ( xand dx) 中拉出的数字
var box = {
x:x,
y: y-font.ascent/font.unitsPerEm * fontSize,
width: width
height: height
}
Run Code Online (Sandbox Code Playgroud)
希望它可以帮助别人!
| 归档时间: |
|
| 查看次数: |
625 次 |
| 最近记录: |