计算SVG文本高度和宽度的正确方法

12

我需要计算svg文本元素的高度和宽度。有没有一种方法可以在不将其添加到页面的DOM中的情况下进行计算?我只需要测量值而不是实际元素。

我只使用纯JavaScript,不使用d3或Raphael。(也许我应该在我的计算中使用其中一个?)

我想要的就是像PHP中的imagettfbbox函数一样的函数,但是用纯JavaScript编写是否容易?还是已经有这样的东西存在了?

由于我实际上并没有使用文本元素,所以将它们添加并隐藏它们对我来说似乎很奇怪(我还在某个地方读到Firefox有问题计算隐藏元素的bbox,Calculating vertical height of a SVG text)。但也许这是唯一的方法?那么我需要在这种情况下使用透明度吗?之后我要如何销毁元素?


将其添加到页面的DOM中会有什么问题? - Robert Longson
你是如何创建文本元素的?你是使用像d3.js或Raphael这样的库,还是使用document.createElement(),或者完全不同的东西?给我们一些上下文。 - jshanley
感谢您的评论。我尝试提供更多的背景信息。 - Daniel
你可以使用canvas元素的measureText方法。 - defghi1977
1
不幸的是,使用measureText似乎失去了测量SVG-text元素内部可以使用的H<tspan style="baseline-shift:sub;font-size:5px">2</tspan>O的能力。因此,这个解决方案似乎行不通。 - Daniel
2个回答

20

也许没有好的方法可以完全达到我追求的目标。但是,如果放弃“实际上将其添加到页面的DOM中”的部分,下面的函数似乎可以实现我的目标。

function bboxText( svgDocument, string ) {
    var data = svgDocument.createTextNode( string );

    var svgElement = svgDocument.createElementNS( svgns, "text" );
    svgElement.appendChild(data);

    svgDocument.documentElement.appendChild( svgElement );

    var bbox = svgElement.getBBox();

    svgElement.parentNode.removeChild(svgElement);

    return bbox;
}

编辑:

关于高度的计算说明:返回的bbox高度,即bbox.height,总是字形的完整高度,例如aA的高度相同。我无法找到更精确计算它们的方法。

但是,可以计算大写带重音符号的高度,例如Ä。这只需要 bbox 的 y 坐标的负值,即-bbox.y

使用这个方法可以计算一些垂直对齐的坐标。例如,为了模拟设置为 text-before-edgetext-after-edgecentraldominantBaseline 属性,可以进行如下计算:

text-before-edge: dy = -bbox.y

text-after-edge: dy = -bbox.height -bbox.y

central: dy = -bbox.y -bbox.height/2

其中,dy 是垂直偏移量。这可以用来解决某些应用程序不支持通过属性设置这些对齐方式的限制。


你是否将此作为“生产”解决方案使用,最终是否找到了更好的方法来完成它而不需要添加元素(我认为这样会慢一些)? - Tomer Cagan
很遗憾,我还没有找到更好的方法。 - Daniel

0

我在VB.Net中遇到了类似的问题!

我编写了一个VB.Net程序来生成SVG文件,需要计算文本宽度以计算下一个垂直条的位置,就像您在以下图像中所看到的那样。

enter image description here

在计算A行元素的最大文本宽度时,B线垂直条被定位。

要在控制台VB.Net应用程序中执行此操作,我执行以下代码:

Private Sub WriteTextInfo(sInfo As String)

    If sInfo <> "" Then
        'display Text in SVG file
        sw.WriteLine("<text x ='" & (xPos + 10) & "' y='" & yPos & "' fill='black' font-family='Arial' font-size='20'>" & sInfo & "</text>")

        'Create Font object as defined in <text> SVG tag 
        Dim font As New Font("Arial", 20.0F)
        'Compute width of text in pixels
        Dim xSize = TextRenderer.MeasureText(sInfo, font)
        'Divide pixels witdh by a factor 1.4 to obtain SVG width !
        Dim iWidth As Decimal = Math.Truncate(CDec(xSize.Width) / 1.4)

        'If new vertical position is greater than old vertical position
        If xPos + iWidth > xPosMax Then
            xPosMax = xPos + iWidth
        End If
    End If
End Sub

总之,我使用TextRenderer.MeasureText()函数计算文本的像素宽度,然后将此数字除以1.4以获得SVG宽度。
1.4的值是相对于我的情况进行实验得出的!
为了使用TextRendered和Font对象,我已经添加了引用。
System.Drawing
System.Windows.Forms

正如您所看到的,我没有使用任何DOM方法来计算文本的宽度,因为我在VB.Net程序中计算它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接