How to position an SVG circle along another circle's path - javascript

I'm building a Gauge chart in a presentational component in React.
I just need to pass it a percentage and let the component do the rest. I can't use any animations because I'm taking a screenshot of the component to place the image in a Powerpoint presentation.
Here's a screenshot of what I'm trying to do:
As you can see in my code snippet, the circle <marker> is being positioned at the end of the grey <path> instead of at the end of the green <path>. How could I position the circle so it sits at the stroke-linecap of the green <path> as in the image above?
Here's the HTML code I have so far:
<div style="width:400px">
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<defs>
<marker
id="dot"
viewBox="0 0 10 10"
refX="4"
refY="4"
markerWidth="4"
markerHeight="4"
>
<circle
cx="4"
cy="4"
r="2"
fill="#FFFFFF"
stroke="#008000"
stroke-width="2"
/>
</marker>
</defs>
<path d="M20,60a35,35 0 1,1 60,0" stroke="#D3D7DB" stroke-width="4" fill="none" stroke-linecap="round"></path>
<path d="M20,60a35,35 0 1,1 60,0" stroke="#008000" stroke-width="6" pathLength="100" fill="none" stroke-linecap="round" stroke-dasharray="75 35" marker-end="url(#dot)"></path>
</svg>
</div>

You can do it all in SVG by setting pathLength and using animationMotion to position the circle.
Some JavaScript and a W3C standard Web Component (supported in all modern Browsers) help in putting multiple gauges on screen and making them dynamic.
customElements.define("svg-gauge", class extends HTMLElement {
connectedCallback() {
let speed = 0.5; // set to 0.0001 for instant display!
let arc = "M20,60a35,35 0 1,1 60,0";
let col = this.getAttribute("color") || "green";
this.innerHTML =
`<input type="range" min="0" max="100" step="5" value="0"`+ // delete 2 lines
` oninput="this.parentNode.percent=this.value" /><br>`+ // just for demo
`<svg viewbox="0 0 100 100">
<path d="${arc}" stroke="grey" stroke-width="6" fill="none" stroke-linecap="round"></path>
<path id="P" d="${arc}" stroke="${col}" stroke-width="8" pathLength="100" fill="none" stroke-linecap="round" stroke-dasharray="75 35"/>
<circle stroke="${col}" cx="0" cy="0" fill="#fff" r="4" stroke-width="3">
<animateMotion dur="${speed}s" path="${arc}" keyPoints="0;0.75" fill="freeze" keyTimes="0;1" calcMode="linear"/>
</circle>
<text x="50%" y="40%" text-anchor="middle">XXX</text>
</svg>`;
this.style.display='inline-block';
this.percent = this.getAttribute("value") || "50";
}
set percent(val = 0) {
this.setAttribute("value", val);
let dash = val + " " + (105 - val);
this.querySelector("#P").setAttribute('stroke-dasharray', dash);
this.querySelector("animateMotion").setAttribute('keyPoints', '0;'+val/100);
this.querySelector("text").innerHTML =`${val} %`;
this.querySelector("animateMotion").beginElement();
this.querySelector("input").value = val;
}
})
<svg-gauge value="35" color="red" ></svg-gauge>
<svg-gauge value="50" color="orange"></svg-gauge>
<svg-gauge value="75" color="green" ></svg-gauge>

I went ahead and accepted Danny '365CSI' Engelman's answer above, but just in case anyone wants to do this without the animations here is how I ended up implementing it:
<div style="width:400px">
<svg viewBox="0 -10 100 100" xmlns="http://www.w3.org/2000/svg">
<path d="M20,60a35,35 0 1,1 60,0" stroke="#D3D7DB" stroke-width="4" fill="none" stroke-linecap="round"></path>
<path d="M20,60a35,35 0 1,1 60,0" stroke="#008000" stroke-width="6" pathLength="100" fill="none" stroke-linecap="round" stroke-dasharray="50 85"></path>
<circle
cx="0"
cy="0"
r="6"
stroke-width="6"
fill="#FFFFFF"
stroke="#008000"
>
<animateMotion
begin="0s"
dur="infinite"
repeatCount="infinite"
keyPoints="0.5;0.5"
fill="freeze"
keyTimes="0;1"
calcMode="linear"
path="M20,60a35,35 0 1,1 60,0"
></animateMotion>
</circle>
</svg>
</div>

Related

Fill Percentage area in a custom Progress Bar SVG

I am new to SVG and stuck with a small task.
I would like to fill a custom SVG to a specific percentage.
Here is my initial SVG
<svg width="233" height="9" viewBox="0 0 233 9" fill="none" xmlns="http://www.w3.org/2000/svg"><path id="base1" d="M0.0104229 4.53685C0.585564 0.0541843 77.5774 0.498692 134.721 1.59593C171.989 2.31113 232.913 -0.235688 232.75 4.22739C232.525 10.3451 134.045 7.87626 89.0013 7.23356C39.1891 6.52242 -0.727053 10.2816 0.0104229 4.53685Z" fill="#DADBDD"></path></svg>
Here is my final SVG
<svg width="233" height="9" viewBox="0 0 233 9" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0.0104229 4.53685C0.585564 0.0541843 77.5774 0.498692 134.721 1.59593C171.989 2.31113 232.913 -0.235688 232.75 4.22739C232.525 10.3451 134.045 7.87626 89.0013 7.23356C39.1891 6.52242 -0.727053 10.2816 0.0104229 4.53685Z" fill="#DADBDD" />
<mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="233" height="9">
<path d="M0.0104229 4.53685C0.585564 0.0541843 77.5774 0.498692 134.721 1.59593C171.989 2.31113 232.913 -0.235688 232.75 4.22739C232.525 10.3451 134.045 7.87626 89.0013 7.23356C39.1891 6.52242 -0.727053 10.2816 0.0104229 4.53685Z" fill="#DADBDD" />
</mask>
<g mask="url(#mask0)">
<ellipse rx="49.9644" ry="25.4799" transform="matrix(0.943377 0.331722 -0.657906 0.7531 34.4845 13.7852)" fill="#ED718F" />
</g>
</svg>
I want to fill this with the percentage area as entered by the user.
Any help will be highly appreciated
As I've commented: if you want to use a maska mask you can use a thick line (stroke-width="9" - for example) instead of the ellipse, and you can mask this line. Then you can change the stroke-dasharray according to the percentage you have.
//the total length of the line which in this case is as long as the shape
let tl = theLine.getTotalLength();
// the percentage for the progress
let xperc = itr.value;
onInput();
itr.addEventListener("input", onInput);
// a function that is setting the value for the stroke-dasharray of the line according with the progress
function onInput() {
xperc = itr.value;
theLine.setAttribute("stroke-dasharray", `${tl * xperc} ${tl - tl * xperc}`);
}
<input id="itr" type="range" min="0" max="1" value="0.35" step=".001" /><br>
<svg width="233" height="9" viewBox="0 0 233 9" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<path id="theShape" d="M0.0104229 4.53685C0.585564 0.0541843 77.5774 0.498692 134.721 1.59593C171.989 2.31113 232.913 -0.235688 232.75 4.22739C232.525 10.3451 134.045 7.87626 89.0013 7.23356C39.1891 6.52242 -0.727053 10.2816 0.0104229 4.53685Z" />
<mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="233" height="9">
<use xlink:href="#theShape" fill="#fff" />
</mask>
</defs>
<use xlink:href="#theShape" fill="#DADBDD" />
<path id="theLine" d="M0 4.5L233 4.5" stroke="#ED718F" stroke-width="9" mask="url(#mask0)" />
</svg>

How to change fill color SVG object for specific path id via AngularJS

svg:
<path id="svg_1" stroke-width="0.5" stroke="black" fill="none" d="m50.610001,63.470001l12.869999,0m0,0l0,464.709991m0,0l-12.869999,0m0,0l0,-464.709991"/>
<path id="svg_2" stroke-width="0.5" stroke="black" fill="none" d="m66.529999,260.670013l12.870003,0m0,0l-0.029999,267.519989m0,0l-12.870003,0m0,0l0.029999,-267.519989"/>
<path id="svg_3" stroke-width="0.5" stroke="black" fill="none" d="m66.519997,275.440002l-3.039997,0"/>
html:
<div ng-include="'example.svg'"></div>
I would like to change fill color for id="svg_2" for example on button click, How to do it?
The problem are your paths. After every line you are using a move to command (m) where you are moving to the last point. I've rewritten the first 2 paths bu removing the move to (m0,0) Now the paths can be filled. The third path is just a line.
Now you can fill the paths using css or bu resetting the value of the attribute fill
path{fill:red}
<svg viewBox="0 0 130 600" width="100">
<path id="svg_1" stroke-width="0.5" stroke="black" fill="none" d="M50.610001,63.470001l12.869999,0
l0,464.709991
l-12.869999,0
l0,-464.709991"/>
<path id="svg_2" stroke-width="0.5" stroke="black" fill="none" d="M66.529999,260.670013l12.870003,0
l-0.029999,267.519989
l-12.870003,0
l0.029999,-267.519989"/>
<path id="svg_3" stroke-width="0.5" stroke="black" fill="none" d="m66.519997,275.440002l-3.039997,0"/>
</svg>

How to center an SVG element based on another element using js?

I made an SVG face and want to center each pupil in their respective eye.
I tried doing this by getting the center of the eye using getBoundingClientRect(). However when I set the position of the pupil this way it didn't work as expected (it did not center, and changes location based on size of page).
I'm guessing getBoundingClientRect() is related to a global position and the cx, cy attributes are local, but it's not clear to me what the attributes are local to or how I would fix it
Any ideas why this doesn't work and what approach might fix it?
Code
// Center the pupil in the eye. Side param is "left" or "right"
function center_pupil(side) {
let eye = document.querySelector(`#${side}-eye`).getBoundingClientRect()
let pupil = document.querySelector(`#${side}-pupil`)
let pupil_radius = pupil.getAttribute("r")
pupil.setAttribute("cx", eye.left + eye.width / 2 - pupil_radius)
pupil.setAttribute("cy", eye.top + eye.height / 2 - pupil_radius)
}
center_pupil("left")
center_pupil("right")
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 645.72 579.45">
<defs>
<clipPath id="clip-path" transform="translate(-114.91 -242.55)">
<path d="M544,377s9-21,54-25c0,0,114-7,150,25s-43,86-43,86-33.77,18.6-79.06,11.62C615.11,473,587.67,468.87,563,448c-10.53-8.91-25.76-21.79-27-42C535.2,393.05,540.49,382.61,544,377Z"
fill="none" />
</clipPath>
<clipPath id="clip-path-2" transform="translate(-114.91 -242.55)">
<path d="M117.5,397.5a38.69,38.69,0,0,1,8-11c6.89-6.57,14.55-8.78,19-10,32.47-8.93,45-10,45-10,34.68-2.95,53.54-4.56,81-1,33.83,4.38,50.79,6.54,61,21,13.58,19.24,5,45.13,4,48-6.94,20.08-23.19,30.46-35,38a106,106,0,0,1-29.07,12.82,108,108,0,0,1-39.93,3.18c-4.63.72-54.1,7.55-88.32-28.91C120.39,435.31,117.91,406.25,117.5,397.5Z"
fill="none" />
</clipPath>
</defs>
<title>face</title>
<g id="eyes">
<g id="right-eye">
<path d="M540.89,375.37A28.23,28.23,0,0,1,548.4,367a24,24,0,0,1,2.19-1.6c.76-.5,1.5-1,2.26-1.48,1.56-.86,3.07-1.81,4.67-2.55s3.14-1.57,4.76-2.23c.8-.34,1.6-.69,2.39-1.06l2.42-.94c.81-.31,1.61-.65,2.42-1s1.64-.56,2.46-.85l2.46-.81a25.18,25.18,0,0,1,2.49-.73c1.68-.43,3.34-.91,5-1.36s3.38-.71,5.07-1.07l2.54-.55,2.56-.41,5.14-.82c1.81-.26,3.45-.36,5.17-.53l5.12-.43q5.12-.4,10.23-.65a289.41,289.41,0,0,1,41,.71c6.82.65,13.62,1.57,20.39,2.63s13.51,2.37,20.23,3.71,13.41,2.9,20.15,4.54c1.69.38,3.36.86,5,1.36l2.51.73c.83.26,1.65.58,2.48.87l2.47.9c.82.3,1.61.71,2.42,1.05a49,49,0,0,1,4.78,2.33,52.84,52.84,0,0,1,4.63,2.72l2.26,1.48c.75.49,1.44,1.12,2.16,1.68l2.12,1.72c.67.65,1.37,1.27,2,2a30,30,0,0,1,3.57,4.42c.57.78,1,1.65,1.5,2.47s.88,1.73,1.21,2.64a25.41,25.41,0,0,1,1.57,5.59,29.78,29.78,0,0,1-.37,11.31c-4.58,14.09-13,25.18-22.33,35.35a178.89,178.89,0,0,1-14.84,14.31q-3.88,3.39-8,6.53c-2.72,2.11-5.44,4.15-8.32,6.15l-.11.08-.1.05c-2.33,1.23-4.54,2.18-6.86,3.13s-4.62,1.77-7,2.58c-4.68,1.57-9.43,2.87-14.23,4a151.83,151.83,0,0,1-29.28,3.67c-2.46,0-4.93.12-7.39.07l-7.41-.31-7.38-.71c-2.46-.23-4.85-.58-7.3-.93a131.55,131.55,0,0,1-28.88-7.35,114.07,114.07,0,0,1-13.69-6.28c-2.25-1.13-4.38-2.49-6.55-3.78-1.08-.65-2.09-1.41-3.14-2.11s-2.12-1.4-3.1-2.19a143.74,143.74,0,0,1-11.34-9.74,83.58,83.58,0,0,1-10.05-11.51A57.13,57.13,0,0,1,535.46,420a53.51,53.51,0,0,1-2.89-15.38,48.4,48.4,0,0,1,2-15.44,50,50,0,0,1,2.7-7.28c.54-1.17,1.12-2.32,1.76-3.44.31-.56.64-1.11,1-1.65S540.59,375.83,540.89,375.37Zm6.22,3.26c-.75,1.3-1.25,2.21-1.77,3.23s-1,2-1.52,3a56.3,56.3,0,0,0-2.49,6.29,41.51,41.51,0,0,0-2,13.2,34.3,34.3,0,0,0,2.84,12.95,45.72,45.72,0,0,0,7.15,11.32,91.37,91.37,0,0,0,9.77,9.7c3.46,3.07,7.29,6.18,10.83,9a112.56,112.56,0,0,0,23.73,14.54,121.21,121.21,0,0,0,13.15,5,135,135,0,0,0,13.72,3.63c2.31.47,4.7,1,7,1.32s4.69.73,7,1l7.1.56c2.37.13,4.75.12,7.13.18a128.42,128.42,0,0,0,28.29-3.39,135,135,0,0,0,13.69-4c2.23-.81,4.46-1.64,6.63-2.57s4.39-1.91,6.33-3l-.21.13c5.43-3.8,10.71-8.06,15.86-12.34s10.1-8.85,14.78-13.63a103.24,103.24,0,0,0,12.64-15.43,47.41,47.41,0,0,0,4.69-8.65,40.34,40.34,0,0,0,2.28-9.25,33.29,33.29,0,0,0,.35-4.54,22.19,22.19,0,0,0-.46-4.4,20.11,20.11,0,0,0-1.34-4.15c-.25-.67-.64-1.3-1-1.95s-.74-1.27-1.2-1.86a29.21,29.21,0,0,0-6.38-6.48c-.62-.47-1.2-1-1.86-1.44l-2-1.34a46,46,0,0,0-4.12-2.49c-11.39-6-24.05-11.23-37.37-13.24-13.25-2.37-26.77-3-40.22-3.48s-26.92-1-40.43-1.38l-10.13-.24-5.07-.07c-1.66,0-3.42,0-5,0a108.23,108.23,0,0,0-19.78,2.72,24.43,24.43,0,0,0-2.41.65l-2.39.72a43.68,43.68,0,0,0-4.71,1.63c-.77.32-1.55.6-2.3.94s-1.48.75-2.21,1.14-1.47.74-2.17,1.18l-2.06,1.35-1,.68c-.33.24-.64.51-1,.76l-1.9,1.53c-.6.54-1.18,1.11-1.76,1.65a20.72,20.72,0,0,0-1.67,1.71c-.54.58-1.07,1.17-1.54,1.78a21.79,21.79,0,0,0-1.41,1.83l-.66.93-.59.93c-.21.31-.34.62-.52.93-.09.15-.15.29-.22.43Z"
transform="translate(-114.91 -242.55)" />
</g>
<path d="M505,327" transform="translate(-114.91 -242.55)" />
<g id="left-eye">
<path d="M114.91,397a8.77,8.77,0,0,1,.41-1.29c.07-.21.14-.43.22-.65.15-.43.33-.85.52-1.27a23.67,23.67,0,0,1,1.3-2.43,33.63,33.63,0,0,1,3.35-4.38,39.68,39.68,0,0,1,8.37-7.14,45.38,45.38,0,0,1,9.88-4.59c3.45-1.11,6.75-1.8,10-2.64,6.64-1.59,13.29-3.11,20-4.49,3.35-.68,6.71-1.32,10.08-1.9,1.69-.29,3.38-.58,5.08-.84l2.56-.36,1.29-.16.66-.08.33,0,.17,0,.34,0h-.15l10-.79c3.36-.27,6.71-.48,10.05-1s6.66-1.26,10-1.68,6.74-.55,10.13-.72c6.78-.27,13.6-.4,20.41-.06s13.6.93,20.33,1.86,13.33,1.84,20,2.91a156,156,0,0,1,20.08,4.29c.83.26,1.66.55,2.49.83s1.65.56,2.47.91l2.45,1,2.4,1.19a37.88,37.88,0,0,1,8.79,6.29,39.43,39.43,0,0,1,6.43,8.62,19,19,0,0,1,1.21,2.38l1.11,2.43.86,2.52a18.46,18.46,0,0,1,.77,2.53,57.7,57.7,0,0,1,1.39,20.78,77.82,77.82,0,0,1-1.71,10.2c-.41,1.68-.84,3.35-1.38,5s-1.2,3.27-1.82,4.9a80.14,80.14,0,0,1-10.73,18l-.83,1-.87,1c-.6.64-1.17,1.32-1.79,1.94-1.24,1.23-2.49,2.46-3.82,3.59a93.34,93.34,0,0,1-8.31,6.24c-1.42.95-2.85,1.9-4.28,2.81s-2.82,1.81-4.32,2.74q-4.45,2.71-9.14,5a111.57,111.57,0,0,1-19.45,7.27,109.85,109.85,0,0,1-41.18,3l.81,0a96.63,96.63,0,0,1-10.64.84c-3.53.09-7.06,0-10.58-.18a118,118,0,0,1-20.88-3.16A104.42,104.42,0,0,1,170,482a97.9,97.9,0,0,1-18-11.15,94.11,94.11,0,0,1-26.21-32.74,104.55,104.55,0,0,1-7.36-19.73q-1.36-5.09-2.24-10.3c-.28-1.74-.57-3.48-.77-5.23-.12-.87-.2-1.75-.29-2.63l-.07-.66-.07-.86C114.94,398.15,114.92,397.55,114.91,397Zm5.18,1.08a7,7,0,0,1,.08.79l0,1.06c.05.83.09,1.67.17,2.5.11,1.68.31,3.34.51,5,.46,3.33,1.1,6.63,1.88,9.91.39,1.63.86,3.25,1.32,4.86s1,3.21,1.62,4.78c1.17,3.15,2.48,6.25,4,9.27a87.88,87.88,0,0,0,42.45,41.16,99.57,99.57,0,0,0,19,6.34,112.17,112.17,0,0,0,19.92,2.62c3.35.14,6.71.15,10.05,0a89,89,0,0,0,9.9-.94l.38-.06.43,0a105.31,105.31,0,0,0,19.53.1A110.47,110.47,0,0,0,270.55,482a104.55,104.55,0,0,0,18.21-6.92,96.58,96.58,0,0,0,8.52-4.71c1.36-.84,2.79-1.77,4.18-2.67s2.76-1.83,4.12-2.75c2.72-1.85,5.3-3.82,7.85-5.8s5-4,7.4-6.21a51.27,51.27,0,0,0,6.53-7.12,42.86,42.86,0,0,0,4.84-8.38,61.67,61.67,0,0,0,4.57-18.91,52.32,52.32,0,0,0-1.7-19.18,18.18,18.18,0,0,0-.76-2.26l-.84-2.22-1.06-2.12a16.05,16.05,0,0,0-1.13-2.08,35,35,0,0,0-5.82-7.29,34.22,34.22,0,0,0-7.68-5.19l-2.14-1-2.23-.86c-.73-.3-1.5-.55-2.27-.78s-1.53-.49-2.31-.71a160.49,160.49,0,0,0-19.39-3.74c-6.59-.93-13.26-1.73-19.92-2.52a264.5,264.5,0,0,0-39.7-1.74c-3.33.07-6.65.33-10,.27s-6.72-.28-10.08-.29a96.26,96.26,0,0,0-10.05.57l-10,.9h-.16l-2.26.33-2.48.41c-1.65.29-3.3.61-4.95.95-3.3.7-6.59,1.48-9.87,2.28-6.56,1.62-13.08,3.42-19.58,5.32-3.23,1-6.56,1.86-9.53,3a39,39,0,0,0-8.42,4.28,34.43,34.43,0,0,0-6.92,6.22,46.51,46.51,0,0,0-2.8,3.73l-1.37,1.92-.7,1-.37.48A.39.39,0,0,0,120.09,398Z"
transform="translate(-114.91 -242.55)" />
</g>
</g>
<g clip-path="url(#clip-path)">
<circle id="right-pupil" cx="532.09" cy="125.45" r="31" />
</g>
<g clip-path="url(#clip-path-2)">
<circle id="left-pupil" cx="116.59" cy="139.95" r="31" />
</g>
<g id="Layer_4" data-name="Layer 4">
<path d="M505,264s120-29,194-10" transform="translate(-114.91 -242.55)" fill="none" stroke="#000"
stroke-miterlimit="10" stroke-width="10" />
<path d="M154,280s116-27,179,0" transform="translate(-114.91 -242.55)" fill="none" stroke="#000"
stroke-miterlimit="10" stroke-width="10" />
<path d="M390,401c9.15,143.49,6.63,190.63,2,205,0,0-6.53,20.28-2,41a35.35,35.35,0,0,0,4,10s1.3,2.14,8,10"
transform="translate(-114.91 -242.55)" fill="none" stroke="#000" stroke-miterlimit="10"
stroke-width="10" />
<line x1="321.09" y1="415.45" x2="329.09" y2="424.45" fill="none" stroke="#000" stroke-miterlimit="10"
stroke-width="10" />
<path d="M363,774l146-4s-1,47-73,47S363,774,363,774Z" transform="translate(-114.91 -242.55)" fill="none"
stroke="#000" stroke-miterlimit="10" stroke-width="10" />
</g>
</svg>
What I'm currently seeing
Note: pupil location changes based on screen size

Change animated object

I have a svg animation like this:
<svg width="500" height="350" viewBox="0 0 500 350">
<path id="motionPath" fill="none" stroke="#000000" stroke-miterlimit="10" d="M202.4,58.3c-13.8,0.1-33.3,0.4-44.8,9.2
c-14,10.7-26.2,29.2-31.9,45.6c-7.8,22.2-13.5,48-3.5,70.2c12.8,28.2,47.1,43.6,68.8,63.6c19.6,18.1,43.4,26.1,69.5,29.4
c21.7,2.7,43.6,3.3,65.4,4.7c19.4,1.3,33.9-7.7,51.2-15.3c24.4-10.7,38.2-44,40.9-68.9c1.8-16.7,3.4-34.9-10.3-46.5
c-9.5-8-22.6-8.1-33.2-14.1c-13.7-7.7-27.4-17.2-39.7-26.8c-5.4-4.2-10.4-8.8-15.8-12.9c-4.5-3.5-8.1-8.3-13.2-11
c-6.2-3.3-14.3-5.4-20.9-8.2c-5-2.1-9.5-5.2-14.3-7.6c-6.5-3.3-12.1-7.4-19.3-8.9c-6-1.2-12.4-1.3-18.6-1.5
C222.5,59,212.5,57.8,202.4,58.3"/>
<circle id="circle" r="10" cx="0" cy="0" fill="tomato" />
<animateMotion
xlink:href="#circle"
dur="5s"
begin="0s"
fill="freeze"
repeatCount="indefinite">
<mpath xlink:href="#motionPath" />
</animateMotion>
</svg>
But instead of circle, I have some svg-image, and I need to change this image to another image in some stage of animation.
<svg width="50" height="35" viewBox="0 0 500 350">
<path id="motionPath1" fill="none" stroke="rgba(255, 255, 255, 0.3)" stroke-miterlimit="10" d="M 100 50 C 150 600 650 600 700 50 "/>
<foreignObject transform="scale(0.5), translate(-25, -25)" id="car1" width="160" height="160"
>
<svg xmlns="http://www.w3.org/2000/svg"><path class="ytp-large-play-button-bg" d="M66.52,7.74c-0.78-2.93-2.49-5.41-5.42-6.19C55.79,.13,34,0,34,0S12.21,.13,6.9,1.55 C3.97,2.33,2.27,4.81,1.48,7.74C0.06,13.05,0,24,0,24s0.06,10.95,1.48,16.26c0.78,2.93,2.49,5.41,5.42,6.19 C12.21,47.87,34,48,34,48s21.79-0.13,27.1-1.55c2.93-0.78,4.64-3.26,5.42-6.19C67.94,34.95,68,24,68,24S67.94,13.05,66.52,7.74z" fill="#f00" fill-opacity="1"></path><path d="M 45,24 27,14 27,34" fill="#fff"></path></svg>
</foreignObject>
<animateMotion xlink:href="#car1" dur="8s" begin="1.3s" fill="freeze" repeatCount="indefinite" rotate="auto-reverse">
<mpath xlink:href="#motionPath1" />
</animateMotion>
</svg>

CSS JS animate image along path and make dashes afterwards

I would like to animate an image on a path and show the route of the object (e.g a plane flying over a map). It should look like on this image:
But the dashes should apply after the object has reached the position, so the dashes were shown after the object.
I have tried multiple times, but I can do only once. Dash animation or plane on path . Does someone knows a solution.
animate a mask over the dashed path
move the plane along the same path
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1" height="200" width="400">
<defs>
<path id="basePath" d="M 50,150 A 280 500 0 0 1 350,150" />
<mask id="mask">
<use xlink:href="#basePath" stroke-width="3" stroke="white"
stroke-dasharray="1000,0" fill="none">
<animate attributeName="stroke-dasharray" from="0,348.5" to="348.5,0"
begin="0s" dur="5s" fill="freeze" />
</use>
</mask>
</defs>
<circle r="4" cx="50" cy="150" fill="grey" />
<circle r="4" cx="350" cy="150" fill="grey" />
<use xlink:href="#basePath" stroke-width="2" stroke-dasharray="10"
stroke="grey" fill="none" mask="url(#mask)"/>
<path d="M 27,3 H 21 L 13,15 H 9 L 12,3 H 5 L 3,7 H -1 L 1,0 -1,-7 H 3 L 5,-3 H 12 L 9,-15 H 13 L 21,-3 H 27 C 33,-3 33,3 27,3 Z"
fill="white" stroke="black" stroke-width="1.5">
<animateMotion rotate="auto" begin="0s" dur="5s" fill="freeze">
<mpath xlink:href="#basePath"/>
</animateMotion>
</path>
</svg>
The main thing to do is to calculate the length of the path, so you can set the stroke-dasharray values for the mask animation such that they keep pace with the animated plane. You can get that length in Javascript with
document.querySelector('#basePath').getTotalLength()

Categories

Resources