'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 |