计算 SVG 文本高度和宽度的正确方法
Posted
技术标签:
【中文标题】计算 SVG 文本高度和宽度的正确方法【英文标题】:Proper way to calculate the height and width of a SVG text 【发布时间】:2014-06-02 06:26:33 【问题描述】:我需要计算 svg 文本元素的高度和宽度。有没有办法在不实际将其添加到我页面的 DOM 的情况下这样做?我只需要度量而不是实际元素。
我既没有使用 d3 也没有使用 Raphael,而只使用了纯 javascript。 (也许我应该使用前者之一进行计算?)
我所追求的只是 php 中的 imagettfbbox
之类的函数,但在纯 JavaScript 中。有这样的事吗?还是写起来容易?
因为我实际上并没有使用文本元素,所以添加和隐藏它们对我来说似乎很奇怪(我还在某处读到 Firefox 在计算隐藏元素的 bbox 时遇到问题,Calculating vertical height of a SVG text)。但也许这是唯一的出路?在这种情况下,我必须使用不透明度吗?之后我会以某种方式销毁元素吗?
【问题讨论】:
为什么将它添加到页面的 DOM 会成为问题? 你是如何创建文本元素的?您是在使用像 d3.js 或 Raphael 这样的库,还是在使用 document.createElement(),或者完全不同的东西?给我们一些背景 感谢您的 cmets。我试图提供更多背景信息。 可以使用canvas元素的measureText方法。 不幸的是,使用 measureText 我似乎失去了测量H<tspan style="baseline-shift:sub;font-size:5px">2</tspan>O
的能力,它可以在 SVG 文本元素中使用。所以这个解决方案似乎不起作用。
【参考方案1】:
也许没有什么好的方法可以实现我所追求的。但是,放弃“没有实际将其添加到我的页面的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
,始终是字形的完整高度,即a
将具有与A
相同的高度。而且我找不到更准确地计算它们的方法。
但是,可以计算大写重音字符的高度,例如Ä
。这将只是 bbox y 坐标的负值,即-bbox.y
。
使用这个可以计算,例如,一些用于垂直对齐的坐标。例如,模拟dominantBaseline
属性设置为text-before-edge
、text-after-edge
和central
。
text-before-edge
:dy = -bbox.y
text-after-edge
:dy = -bbox.height -bbox.y
central
:dy = -bbox.y -bbox.height/2
其中dy
是垂直平移。这可用于绕过某些应用程序的限制,这些应用程序不支持由属性设置的这些对齐方式。
【讨论】:
您是否将其用作“生产”解决方案,最终找到了一种更好的方法来做到这一点而无需实际添加元素(我认为这很慢)? 不幸的是我还没有找到更好的方法。【参考方案2】:我在VB.Net中也遇到过类似的问题!
我编写了一个生成 SVG 文件的 VB.Net 程序,它需要计算文本的宽度来计算下一个垂直条的位置,如下图所示
B 行竖线定位于计算 A 行元素的最大文本宽度。
要在控制台 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 程序中计算的。
【讨论】:
以上是关于计算 SVG 文本高度和宽度的正确方法的主要内容,如果未能解决你的问题,请参考以下文章