Domanda

I need to calculate the height and width of a svg text element. Is there a way to do so without actually adding it to the DOM of my page? I need only the measures not the actual element.

I am using neither d3 nor Raphael, but only plain JavaScript. (Maybe I should use one of the former for my calculations?)

What I am after is just a function like imagettfbbox in PHP, but in plain JavaScript. Is there such a thing? Or is it easy to write?

Since I am not actually using the text elements it seems strange to me to add them and hide them (I also have read somewhere that Firefox has problems with calculating the bbox of hidden elements, Calculating vertical height of a SVG text). But maybe this is the only way to go? Will I have to work with opacity in that case? Do I destroy the element somehow afterwards?

È stato utile?

Soluzione

Maybe there is no good way to achieve exactly what I was after. However, giving up the "without actually adding it to the DOM of my page" part, the following function seems to achieve my goal.

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;
}

Edit:

A note on the calculation of the height: the height of the bbox returned, i.e. bbox.height, is always the full height of the glyph, i.e. a will have the same height as A. And I could not find a way to calculate them more exactly.

However, one can calculate the height of uppercase accented characters, e.g. Ä. This will be just the negative of the y coordinate of the bbox, i.e. -bbox.y.

Using this one can calculate, for example, some coordinates for vertical alignment. For example to emulate the dominantBaseline attribute set to text-before-edge, text-after-edge, and central.

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

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

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

Where dy is the vertical translation. This can be used to get around limitations of some applications that do not support these alignments set by attributes.

Altri suggerimenti

I have encountered a similar problem in VB.Net !

I written a VB.Net program that generate a SVG file and that needs to compute width of text to compute next vertical bar position as you can see in following image

enter image description here

The B line vertical bar is positionned in computing max text width of A line elements.

To do that in Console VB.Net application, I execute following lines of code

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

In resume, I compute text's width in pixels using TextRenderer.MeasureText() function and I divide this number by 1.4 to obtain SVG width.

1.4 value is obtained by experiment relatively to my case !

To use TextRendered and Font objects, I have added reference to

System.Drawing
System.Windows.Forms

As you can see, I don't use any DOM method to compute text's width because I compute it in VB.Net program.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top