SVG Path Completion Demo

Use SVG stroke dash array and dashoffset to animate a stroke along a path.

by the_voder

HTML

<script src=" https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<svg version="1.1" id="Map" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
	 viewBox="0 0 400 400" style="enable-background:new 0 0 400 400;" xml:space="preserve">
<style type="text/css">
	/*
	These CSS styles were generated by Illustrator.
	I have commented them out here, and copied them to a seperate stylesheet
	.st0{fill:none;stroke:#6DB52D;stroke-width:5;stroke-miterlimit:10;stroke-dashoffset:800;}
	st1{fill:#FFFFFF;stroke:#6DB52D;stroke-width:5;stroke-miterlimit:10}
	*/
</style>
<path id="Route" class="st0" d="M317.7,331c-0.7-57.3-18.7-190-46.3-208S146,49.7,111.3,52.7s-75,80.3-73.7,115.7
	c1.3,35.3,47.7,97.3,80.3,100.3S219.3,227,236,271"/>
<circle id="City1" class="st1" cx="317" cy="329.3" r="11.7" data-pathclass="path-to-city1"/>
<circle id="City2" class="st1" cx="305.3" cy="213.6" r="11.7" data-pathclass="path-to-city2"/>
<circle id="City3" class="st1" cx="182.8" cy="74.4" r="11.7" data-pathclass="path-to-city3"/>
<circle id="City4" class="st1" cx="60.3" cy="99.8" r="11.7" data-pathclass="path-to-city4"/>
<circle id="City5" class="st1" cx="235.6" cy="270.2" r="11.7" data-pathclass="path-to-city5"/>
</svg>

CSS

/*
It's good to add comments for the SVG style rules, as they contain value for attributes that standard HTML elements don't have

See: 'Presentation Attributes' section here:
https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute
for a list of SVG attributes that can be targetted by CSS.
*/

/* ======= SVG STYLES ======= */

.st0 {
	fill:none;
	stroke:#6DB52D;
	stroke-width:10px;
	stroke-miterlimit:10;
	stroke-linecap: round;
	/*
	Set path stroke to dashed, with each dash same length as total path length
	See: https://css-tricks.com/svg-line-animation-works/
	*/
	stroke-dasharray: 800;
	/*
	dashoffset set to length of path, to hide stoke initially
	*/
	stroke-dashoffset:800;
	/* CSS3 transition effect to animate offset */
	transition: stroke-dashoffset 1.0s ease;
}

.path-to-city1 { stroke-dashoffset: 800; }
.path-to-city2 { stroke-dashoffset: 680; }
.path-to-city3 { stroke-dashoffset: 480; }
.path-to-city4 { stroke-dashoffset: 330; }
.path-to-city5 { stroke-dashoffset: 0; }


/* Styles for city marker circles */

.st1 {
	transition: 1.0 ease;
	fill: #fff;
	stroke-width: 5px;
	stroke: #6DB52D;
	transition: all 1.0s ease;
}
.st1:hover {
	fill: yellow;
	stroke-width: 10px;
}

JavaScript

$(document).ready(function() {
	
	// Get handle on route path (raw JavaScript, not jQuery)
	//var route = document.querySelector('#Route');
	// ...allows us to get total length of path
	//var routelength = route.getTotalLength();
	// Display total length in alert message
	//alert(routelength);
	// We don't need the above, once we've got the path-length
	
	// jQuery handle to same SVG path
	var $route = $("#Route");
	
	/*
	We can change the 'stroke-dashoffset' value in the CSS '.st0' rule
	and make a list of the offset value for each city, in this case (approximate values):

	City1:	800 (total path length, rounded down)
	City2:	680
	City3:	480
	City4:	330
	City5:	0
	
	We can then create CSS classes that can be applied to the route path using jQuery.
	The name of the class required to draw the line as far as each city is stored on each city marker circle element using a custom data attribute 'data-pathpathclass="<CSS class name>"
	
	We can retrieve these values with jQuery when the marker is clicked or rolled-over, and apply the class to the route element
	*/
	
	$(".st1").click(function() {
		// We can't use jQuery addClass because jQuery can't add classes to SVG element
		// NOTE: we're setting ALL classes applied to element here, so we have to make sure the original class (.st0) is still applied
		// See: http://stackoverflow.com/questions/8638621/jquery-svg-why-cant-i-addclass 1st answer
		$route.attr("class", "st0 " + $(this).data("pathclass"));
	});
	
	// NOTE: this can all be done using raw JavaScript (and actually, the current version of jQuery doesn't deal well with SVG), but if you're using jQuery on your site, anyway, then no reason not to use some jQuery here, too.
});