Foub
Foub

Reputation: 295

SVG object animation on a path line

I want to animate a svg path on a line. Exactly like this codepen but instead of use a polygon, I want to use a more complex svg. (path) Codepen example

Html :

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     width="100%" height="100%" viewBox="0 0 800 300" enable-background="new 0 0 800 300" xml:space="preserve">

    <path d="M30,30 L770,30" />
    <path d="M29.833,113.5C29.833,178.667,99,271.334,257,271.334 S475.5,81,375.5,81S305,271.334,770,271.334"/>

    <polygon points="15,0 18.541,11.459 30,11.459 20.729,18.541 24.271,30 15,22.918 5.729,30 9.271,18.541 0,11.459 11.459,11.459    "/>

    <polygon points="15,0 18.541,11.459 30,11.459 20.729,18.541 24.271,30 15,22.918 5.729,30 9.271,18.541 0,11.459 11.459,11.459    "/>

</svg>

Is anyone know how to replace the polygon by a svg path file ?

Thank you,

Upvotes: 0

Views: 167

Answers (1)

enxaneta
enxaneta

Reputation: 33062

In this example I'm using a complex <symbol> element instead of the star. The <symbol> contains a path and 4 circles. I've putted this symbol in a hidden SVG element.

In the main SVG element I've changed the polygons (stars) with 2 <use> elements that are using the #cow symbol.

In the Javascript I've changed var stars = svgContainer.getElementsByTagName("polygon"); with var stars = svgContainer.getElementsByTagName("use");

You can if you want to change the name of the variable from stars to cows in all your javascript.

/*	A variable to keep track of where we are on the line
	0 = start, 1 = end */
var counter = 0;

/*	A boolean variable to keep track of the direction we want to travel in 
	true = move to the left, false move to the right */
var direction = true;

/*	First get a reference to the enclosing div and then to
	the 2 svg paths */
var svgContainer = document.getElementById("outerWrapper");
var ns = "http://www.w3.org/2000/svg";
var svg = svgContainer.getElementsByTagNameNS(ns, "path");
/*	the var 'svg' contains a reference to two paths so svg.length = 2
	svg[0] is the straight line and svg[1] is the curved lines */

/*	Now get the length of those two paths */
var straightLength = svg[0].getTotalLength();
var curveLength = svg[1].getTotalLength();

/*	Also get a reference to the two star polygons */
var stars = svgContainer.getElementsByTagName("use");

function moveStar() {
	/*	Check to see where the stars are journeys to determine 
		what direction they should be travelling in */
	if (parseInt(counter,10) === 1) {
		/* we've hit the end! */
		direction = false;
	} else if (parseInt(counter,10) < 0) {
		/* we're back at the start! */
		direction = true;
	}

	/*	Based on the direction variable either increase or decrease the counter */
	if (direction) {
		counter += 0.003;
	} else {
		counter -= 0.003;
	}

	/*	Now the magic part. We are able to call .getPointAtLength on the tow paths to return 
		the coordinates at any point along their lengths. We then simply set the stars to be positioned 
		at these coordinates, incrementing along the lengths of the paths */
	stars[0].setAttribute("transform","translate("+ (svg[0].getPointAtLength(counter * straightLength).x -15)  + "," + (svg[0].getPointAtLength(counter * straightLength).y -15) + ")");
	stars[1].setAttribute("transform","translate("+ (svg[1].getPointAtLength(counter * curveLength).x -15)  + "," + (svg[1].getPointAtLength(counter * curveLength).y -15) + ")");

	/*	Use requestAnimationFrame to recursively call moveStar() 60 times a second
		to create the illusion of movement */
	requestAnimationFrame(moveStar);
}
requestAnimationFrame(moveStar);
body {
  margin: 0;
  background: #565279;
}

.outerWrapper {
	width: 800px;
	height: 300px;
	position: relative;
}

.outerWrapper svg {
	position: absolute;
}

.outerWrapper svg path {
	fill:none; 
	stroke:#DABDD8;
	stroke-width:5; 
	stroke-dasharray:10,10;
}

.outerWrapper svg polygon {
	fill:orange; 
}
<svg style="display:none">
	<defs>		
<symbol id="cow" viewBox= "0 0 200 200">
	<path class="head" fill="gold" stroke-width="1" d="M87 110 c5 0 12-0 21-0 c9-0 26 2 33-4 c5-4 2-14 0-19 c-6-11-14-11-25-11c-10-0-15-7-8-16 c11-13 22-2 35-3 c7-0.622 15.812-11.692 5.757-14.441c-3.556-0.973-12.802 0.949-15.412-0.906c6.371 4.5 20.854-11.553 23.774-15.168 c4.103-5.079 7.713-10.561 10.987-16.205c0.678-1.169 2.928-7.366 4.133-7.882c-7.42 3.175-14.234 8.021-22.368 10.7 c-20.585 6.695-42.426 9.711-64.039 9.711c-18.865 0.045-41.083-2.831-60.479-8.723C16.774 10.2 9.1 5 0.6 1.4 C4.425 3 11 19.4 13.8 23.083c3.03 4 18.5 22.6 25.6 17.551c-2.173 1.544-10.67-0.021-13.562 0.5 c-9.382 1.672-7.292 11.8 1 14.308c12.151 3.7 23.371-8.617 35 0.611c7.217 5.7 11.1 18.941-1.428 19.4 c-10.27 0.355-20.138-1.575-26.384 8.23c-4.091 6.423-6.256 13.976-2.265 20.886c3.503 6.1 24.2 4.7 30.3 4.9 C70.382 109.8 78.7 109.9 87 109.8"/>
	
		<circle class="eyeR" fill="#040B13"  stroke-width="1"  cx="117.3" cy="64.9" r="6"/>
		<circle class="eyeL" fill="#040B13"  stroke-width="1"  cx="55.4" cy="64.9" r="6"/>	
		<circle class="nostrilL" fill="#446B70" stroke-width="1"  cx="50.6" cy="92.9" r="9"/>	
		<circle class="nostrilR" fill="#446B70"  stroke-width="1" cx="123.4" cy="92.9" r="9"/>
</symbol>
</defs>	
</svg>

<div class="outerWrapper" id="outerWrapper">

	<svg version="1.1" id="Layer_1"  xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
		 width="100%" height="100%" viewBox="0 0 800 300" enable-background="new 0 0 800 300" xml:space="preserve">
	 
		<path class="pth" d="M30,30 L770,30" />
		<path class="pth" d="M29.833,113.5C29.833,178.667,99,271.334,257,271.334 S475.5,81,375.5,81S305,271.334,770,271.334"/>

		<use xlink:href="#cow" width="30" height="30" />
    <use xlink:href="#cow" width="30" height="30" />
	</svg>
       
</div>

Upvotes: 1

Related Questions