在浏览器中复制文本的边界框 [英] reproduce Bounding Box of text in Browsers

查看:80
本文介绍了在浏览器中复制文本的边界框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在浏览器中使用SVG时,浏览器具有getBBox功能,可为您提供各种元素的边界框.但是,当涉及到文本元素时,这确实使我感到困惑,如何计算该绑定框. 我知道fontsize是基于在字体文件中指定的em-Box的. 但是,我的测试表明,这些方法都无法产生与FF或Chrome相同的结果(在fontsize 1000上仅相差几px):

When using SVG in the Browser the browser has a getBBox function to give you the bounding box of various elements. But when it comes to text elements it really confused me how this bouding box is calculated. I know that fontsize is based on the em-Box which is specified in the font file. However my tests show that none of these produce the same results as in FF or Chrome (which differ only a few px on 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 Ć

那么浏览器中文本的bbox高度背后的秘密是什么?

我什至试图研究FF和Chrome的源代码,但要找到正确的计算基础本身是一个挑战

I even tried to look into the source code of FF and Chrome but finding the right place where the calculation is based is a challenge on its own

//针对评论: 我想像在浏览器中那样计算svg文本的bbox(复制行为).我需要知道正确计算bbox所需的字体规格和用于计算(宽度和高度足够)的公式化器

// In response to the comment: I want to calculate the bbox of svg text as done in the browser (replicate the behavior). I need to know the metrics of the font which are needed to correctly calculate the bbox and the formular which is used to calculate the (width and height is sufficiant)

推荐答案

经过大量的研究和琐碎和错误后,我发现了一种可能的解决方案,至少可以解释文本bbox尺寸的镶边行为.

After lots of reasearch and tril and error I found a possible solution to at least explain chromes behavior of text bbox dimensions.

首先,我使用了npm包 fontkit 来加载和解析字体文件. fontkit总体上为您提供了几种字体指标,包括:

First of all I used the npm package fontkit to load and parse the fontfile. fontkit give you several metrics for the font in a whole which includes:

  • font.ascent
  • font.descent
  • font.lineGap
  • font.unitsPerEm

因此,为了计算bbox的高度,我计算出以下内容:

So to calculate the height of the bbox I figured the following:

bboxHeight = (font.ascent - font.descent + font.lineGap) / unitsPerEm * fontSize

但是,当字体大于em框(font.ascent - font.descent > unitsPerEm)时,这会导致错误.在这种特殊情况下,bboxHeightfont.ascent - font.descent.

However, that leads to errors when having a font which is bigger then the em box (font.ascent - font.descent > unitsPerEm). In this special case the bboxHeight is font.ascent - font.descent.

这将导致以下代码显示高度:

That leads to following code for the height:

var fontHeight = font.ascent - font.descent
var lineHeight = fontHeight > font.unitsPerEm ? fontHeight : fontHeight + font.lineGap
var height = lineHeight/font.unitsPerEm * fontSize


BBox宽度

使用fontkitlayout功能来计算文本的宽度. layout使您可以访问从其提取文本的字形,还可以访问字形的度量.我们需要的度量标准是advanceWidth,其中包括当前glpyh旁其他字形的边距.通过汇总所有advanceWidth并相应地缩放它们,我得到了bboxWidth:


BBox Width

to calculate the width of the text I made use of the layout feature of fontkit. layout gives you access to the glyphs the text is drawn from and also access to the metrics of the glyph. The metric we need is the advanceWidth which includes the margins to other glyphs next to the current glpyh. By summming up all advanceWidths and scaling them accordingly I ended up with the bboxWidth:

var width = font.layout(text).glyphs.reduce((last, curr) => last + curr.advanceWidth, 0)
width = width / font.unitsPerEm * fontSize


BBox y位置

问题不止于此,我们仍然必须计算bbox的y位置.那是一个相当简单的公式:


BBox y position

Trouble does not stop here, we still have to calculate the y position of the bbox. Thats a rather simple formula:

var bboxY = y-font.ascent/font.unitsPerEm * fontSize

y是您从dom(ydy属性)中得出的理论位置

Where y is the theoretical position you would pull from the dom (y and dy attribute)

这就是您从dom(xdx)中拉出的身材

Thats just the figure you pull from the dom (x and dx)

var box = {
    x:x,
    y: y-font.ascent/font.unitsPerEm * fontSize,
    width: width
    height: height
}


希望它对其他人有帮助!


Hope it helps someone else!

这篇关于在浏览器中复制文本的边界框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆