Reputation: 931
I am using vivusjs
library to animate SVG, i want to animate an image file or a shape along animated SVG . somthing like as below:
White line is an animating SVG path and green pen is my image file. i need it in Vivusjs
library.
Upvotes: 3
Views: 480
Reputation: 21193
No need for a library, you can do all with native JavaScript
Create your own JavaScript Web Component (JSWC) <draw-path>
(supported in all modern browsers)
Do all animations with JavaScript. Key is to set the pathLength
to 1 and use getPointAtLength
to position the SVG pen at the correct location.
Then all HTML required to display (see SO snippet below):
is:
<draw-path d='M25 50a25 25 0 1 1 80 0a25 25 0 1 1-80 0'></draw-path>
<draw-path d='M25 25h50v50h-50v-50z' stroke='green' stroke-width='5' speed="0.007"></draw-path>
<draw-path stroke='red' stroke-width='5' speed=".01"></draw-path>
window.customElements.define("draw-path", class extends HTMLElement {
constructor() {
let template = (id) => document.getElementById(id).content.cloneNode(true);
super() // super sets and returns this scope
.attachShadow({mode: "open"}) // sets and returns this.shadowRoot
.append(template(this.nodeName));
this.line = this.shadowRoot.querySelector("#line");
this.line.setAttribute("d", this.getAttribute("d") || "m10 60c30-70 55-70 75 0s55 70 85 0");
this.line.setAttribute("stroke", this.getAttribute("stroke") || "black");
this.line.setAttribute("stroke-width", this.getAttribute("stroke-width") || "2");
this.pen = this.shadowRoot.querySelector("#pen");
this.onmouseover = (evt) => this.draw();
}
connectedCallback() {
this.draw();
}
showpen(state = true, scale) {
this.pen.style.display = state ? 'initial' : 'none';
}
draw() {
clearInterval(this.drawing);
this.showpen();
this.dashoffset = 1;
this.pathlength = this.line.getTotalLength();
this.drawing = setInterval(() => this.update(), 50);
}
update() {
this.dashoffset -= this.getAttribute("speed") || 0.02;
let {x,y} = this.line.getPointAtLength(this.pathlength - this.dashoffset * this.pathlength);
this.pen.setAttribute("transform", `translate(${x-2} ${y-2})`);
this.line.style.strokeDashoffset = this.dashoffset;
if (this.dashoffset <= 0) this.end();
}
end() {
clearInterval(this.drawing);
this.showpen(false);
//console.log("end",this.line);
clearTimeout(this.timeout);
this.timeout = setTimeout(()=>this.draw(),2000);
}
});
<draw-path d='M25 50a25 25 0 1 1 80 0a25 25 0 1 1-80 0'></draw-path>
<draw-path d='M25 25h50v50h-50v-50z' stroke='green' stroke-width='5' speed="0.007"></draw-path>
<draw-path stroke='red' stroke-width='8' speed=".01"></draw-path>
<template id="DRAW-PATH">
<style>
:host { display: inline-block }
svg { width: 180px; height: 130px; background: beige }
</style>
<svg xmlns="http://www.w3.org/2000/svg">
<path id='line' pathlength='1' stroke-dasharray='1' stroke-dashoffse='1' fill='transparent'/>
<path id='pen' stroke='black' stroke-width='2' fill='gold' d='m12 19l7-7l3 3l-7 7l-3-3zm6-6l-2-8l-14-3l4 15l7 1l5-5zm-16-11l8 8m-1 1a2 2 0 104 0a2 2 0 10-4 0'/>
</svg>
</template>
Note:
Be aware M
or m
(moves) in paths create a new stroke, drawn at the same time, not sequentially.
So stroke-dash*
settings are applied concurrent.
That is why in all blogs you only see single stroke simple paths or polylines used.
Upvotes: 7