16

How can I create a box (rect?) that resizes itself to fit the the text inside of it using SVG?

Volker E.
  • 5,911
  • 11
  • 47
  • 64
Asa Ayers
  • 4,854
  • 6
  • 40
  • 57

2 Answers2

8

Sorry the answer took me so long, but I was learning how to use ECMAScript with an XML DOM.

Alright. So suppose you have your document structure like so:

<svg
 xmlns="http://www.w3.org/2000/svg"
 xmlns:svg="http://www.w3.org/2000/svg"
 xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
 xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
 version="1.1"

 width="800"
 height="600"
 id="example_text">

    <g id="layer1">

        <text
         x="123.4"
         y="567.8"
         id="text_holder">

            <tspan id="tspan1">Text</tspan>
            <tspan id="tspan2">More text</tspan>

        </text>
    </g>
    <script type="text/ecmascript">

function create_from_rect (client_rect, offset_px) {
    if (! offset_px) {offset_px=0;}
    var box = document.createElementNS(
        document.rootElement.namespaceURI,
        'rect'
    );

    if (client_rect) {
        box.setAttribute('x', client_rect.left - offset_px);
        box.setAttribute('y', client_rect.top - offset_px);
        box.setAttribute('width', client_rect.width + offset_px * 2);
        box.setAttribute('height', client_rect.height + offset_px * 2);
    }

    return box;
}

function add_bounding_box (text_id, padding) {
    var text_elem = document.getElementById(text_id);
    if (text_elem) {
        var f = text_elem.getClientRects();
        if (f) {
            var bbox = create_from_rect(f[0], padding);
            bbox.setAttribute(
                'style',
                'fill: none;'+
                'stroke: black;'+
                'stroke-width: 0.5px;'
            );
            text_elem.parentNode.appendChild(bbox);
        }
    }
}

add_bounding_box('text_holder', 5);

</script>
</svg>

Adding the <script> tag at the bottom of the root <svg> element causes it to execute after it's created the DOM structure above it, just like JavaScript on a web page.

amphetamachine
  • 27,620
  • 12
  • 60
  • 72
  • Thanks, I'm extremely impressed with your answer. Its much more work to accomplish this than I expected. – Asa Ayers Jun 21 '10 at 22:25
  • I should add that I tried this when displaying in Firefox and it works, but am having trouble getting it to work in Chrome. – amphetamachine Jun 24 '10 at 06:22
2

Would the following approach make things any simpler?

    var text_elem = document.getElementById(text_id);
    var bbox = text_elem.getBBox();

and then use bbox's width and height to draw a rect?

JamieJag
  • 1,541
  • 2
  • 11
  • 18
  • Can you explain how that would make it simpler? How would I use the code your provided? – Asa Ayers Apr 19 '12 at 20:34
  • Unless I've not understood you correctly, all you're looking to do is draw a rectangle around the text, so the rect need only be drawn starting at the text element's x,y and with the bbox's width and height. I haven't tested the code, but I'd hazard the guess that checking for bbox not being null would not be necessary. I was being overly optimistic when I said my approach would simplify things; it would, but not dramatically – JamieJag Apr 20 '12 at 22:31