Search code examples
javascriptsvgtext

Add text to SVG path dynamically


I have an SVG exported from Adobe Illustrator with several paths like this, which produces a small polygon I intend to use as a text box

<svg viewbox="387 390 74 20">
    <g>
        <path class="st37" d="M452,408h-56c-4.42,0-8-3.58-8-8l0,0c0-4.42,3.58-8,8-8h56c4.42,0,8,3.58,8,8l0,0     C460,404.42,456.42,408,452,408z" />
    </g>
</svg>

I'd like to dynamically add text to it. I've seen many similar questions here, but most of them involed specifying a x and y property for a text element based on the x and y property the path element. My path, however, does not have such properties.

I've tried to use a textPath element with xlink:href pointing to my path. I gets attached to the path, but the text wraps my path element instead of being inside it.

So, is there a way to achieve this? I'm open to different solutions here. My dream would be to use javascript to get the path element and add the text from there. But I could also edit the base SVG file to add a text or any other relevant element and attributes to make this work, as long as I can change the text dynamically from javascript later. And since this SVG is produced by Illustrator, I could also try different export options there in order to get a proper output for my goal.


Solution

  • Here's some sample code that takes a label path and adds a <text> element after it with whatever text you choose.

    let label1 = document.querySelector("#label1");
    
    addLabelText(label1, "Something");
    
    
    
    function addLabelText(bgPath, labelText)
    {
       let bbox = bgPath.getBBox();
       let x = bbox.x + bbox.width / 2;
       let y = bbox.y + bbox.height / 2;
       
       // Create a <text> element
       let textElem = document.createElementNS(bgPath.namespaceURI, "text");
       textElem.setAttribute("x", x);
       textElem.setAttribute("y", y);
       // Centre text horizontally at x,y
       textElem.setAttribute("text-anchor", "middle");
       // Give it a class that will determine the text size, colour, etc
       textElem.classList.add("label-text");
       // Set the text
       textElem.textContent = labelText;
       // Add this text element directly after the label background path
       bgPath.after(textElem);
    }
    .st37 {
      fill: linen;
    }
    
    .label-text {
      font-size: 10px;
      fill: rebeccapurple;
      transform: translate(0, 3px); /* adjust vertical position to centre text */
    }
    <svg viewbox="387 390 74 20">
      <g>
        <path id="label1" class="st37" d="M452,408h-56c-4.42,0-8-3.58-8-8l0,0c0-4.42,3.58-8,8-8h56c4.42,0,8,3.58,8,8l0,0     C460,404.42,456.42,408,452,408z" />
      </g>
    </svg>