'Animate reused svg independently

I want some SVGs to animate on click. The SVG is defined once and has been reused multiple times with the <use> tag. I wrote the following code:

svg {
  border: 1px solid #0af;
  stroke: black;
}
<svg display="none">
    <symbol id="tick" viewBox="0 0 100 100">
        <polyline points="15,50 40,75 85,25" style="stroke-width:10; fill:none; stroke-linecap:round; stroke-linejoin:round;" stroke-dasharray="120">
            <animate attributeName="stroke-dashoffset" from="120" to="0" dur="0.5s" fill="freeze" repeatCount="1" begin="click" />
        </polyline>
    </symbol>
</svg>

<svg><use href="#tick"/></svg>
<svg><use href="#tick"/></svg>
<svg><use href="#tick"/></svg>
<svg><use href="#tick"/></svg>

The problem is, if I click on a single SVG, all the instances of that SVG are getting animated, which is not what I want. I want them to animate independently. What is the best way to do this other than embedding the complete SVG multiple times?



Solution 1:[1]

you can put your svg in a file and access it in document tree like this:

<object data="tick.svg"></object>

Solution 2:[2]

Your problem is duplicate ids

create a Web Component (supported in all modern Browsers) that injects your once defined SVG

<svg-tick id=ONE stroke="red"></svg-tick>
<svg-tick id=TWO></svg-tick>
<svg-tick id=THREE></svg-tick>
<svg-tick id=FOUR stroke="blue"></svg-tick>

You can add more Web Component goodies, like attributes and a single clickhandler...

I changed the polyline to path, makes it easier with a pathLength=100, no need for calculations

id not required, you can also generate a unique value with "ID"+new Date()/1

<style>
  svg {
    border: 1px solid #0af;
    stroke: green;
    width: 120px;
    cursor:pointer;
  }
  #TWO svg { stroke: goldenrod;   }
</style>

<svg-tick id=ONE stroke="red"></svg-tick>
<svg-tick id=TWO></svg-tick>
<svg-tick id=THREE></svg-tick>
<svg-tick id=FOUR stroke="blue"></svg-tick>
<script>
  customElements.define('svg-tick', class extends HTMLElement {
    connectedCallback() {
      let id = this.id;
      let stroke = this.hasAttribute("stroke") 
                        ? ` stroke=${this.getAttribute("stroke")} ` 
                        : "";
      this.innerHTML = `
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
    <path id="${id}" d="M15,50 40,75 85,25" pathLength="100" 
        stroke-width="10" fill="none" stroke-linecap="round" stroke-linejoin="round" 
        stroke-dasharray="100" ${stroke}/>
    <animate id="${id}" attributeName="stroke-dashoffset" from="100" to="0" 
           dur="0.5s" fill="freeze" repeatCount="1" begin="click" />
</svg>`;
      this.onclick = (evt) => console.log('clicked',id);
    }
  });
</script>

svga

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 syduki
Solution 2