cak3_lover
cak3_lover

Reputation: 1958

linking textPath with javascript instead of xlink:href in html?

Is there a way to link a textPath to a path directly through javascript?

something like this maybe?

let path=document.querySelector("path");
let txt_path=document.querySelector("textPath");

textPath.href=path
<svg id="svg1" width="1000" height="1000">

<path fill="none" stroke="black" d="M 0 0 L 300 300" stroke-width="3"/>

  <text id="txt1" font-size="24" dy="-10">
    <textPath id="result" text-anchor="middle" startOffset="50%" >
       Hello there
    </textPath>
  </text>

</svg>

The entire idea is that I have too many paths and can't assign an id to every single one & instead directly linking them with javascript would be much more convenient

is something like this even possible? or is there no workaround ids?

Note: I tried this but it doesn't seem to support cross browser

Upvotes: 0

Views: 208

Answers (2)

Robert Longson
Robert Longson

Reputation: 124229

The path needs an id and the textPath then points to that id.

let path=document.querySelector("path");
let textPath=document.querySelector("textPath");

path.id = self.crypto.randomUUID();

textPath.href.baseVal = "#" + path.id;
<svg id="svg1" width="1000" height="1000">

<path fill="none" stroke="black" d="M 0 0 L 300 300" stroke-width="3"/>

  <text id="txt1" font-size="24" dy="-10">
    <textPath id="result" text-anchor="middle" startOffset="50%" >
       Hello there
    </textPath>
  </text>

</svg>

Upvotes: 1

It is all done by ID (only FireFox has the path attribute on textPath)

Write a Web Component, for symantic HTML : <svg-text-path> that generates a unique ID. No shadowDOM required then and all you global CSS applies.

<svg-text-path>Hello</svg-text-path>
<svg-text-path>Wonderful</svg-text-path>
<svg-text-path d="M0,90H180">Web Components</svg-text-path>

<style>
  svg { background:pink }
  textPath { fill: green }
  [d*="H"] svg {background:lightgreen}
</style>

<script>
  customElements.define("svg-text-path", class extends HTMLElement {
    connectedCallback() {
      setTimeout(() => { // make sure innerHTML is parsed
        let id = Math.random()*1e32;
        this.innerHTML = `<svg width="180" height="180">
             <path id="TP${id}" pathLength="100" fill="none" stroke="black" 
                   d="${this.getAttribute("d")||'M0,0L180,180'}" stroke-width="3"/>
             <text font-size="24" dy="-10">
             <textPath href="#TP${id}" text-anchor="middle" startOffset="50" >
              ${this.innerHTML}</textPath></text></svg>`;
        })
      }
    })
</script>

  • Note: You can only create Web Components in the HTML NameSpace extends HTMLElement, alas not (yet) in the SVG NameSpace. But as shown you can use Web Components to create SVG

Upvotes: 0

Related Questions