block by nbremer 25e2db4abc9eaf080190

Text on an Arc - Animate from a Wavy line to an Arc

Full Screen

This is an example from my blog on Placing Texts on Arcs with D3.js that shows that a transition between dissimilar paths (from a wavy line to an arc) can still be accomplished, but that it needs a pathTween function (taken from this example)

Another version shows how a transition between similar paths (both arcs) can be achieved in the default transition way

Other examples of text along a path from the same blog

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
	<title>Text on simple Arc</title>

	<!-- D3.js -->
	<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script>
	<!-- Google Font -->
	<link href='//fonts.googleapis.com/css?family=Pacifico' rel='stylesheet' type='text/css'>
	
	<style>
		body {
			font-family: 'Pacifico', sans-serif;
			fill: #333333;
			font-size: 30px;
			text-align: center;
		}
	</style>
  </head>
  
  <body>
	<div id="chart"></div>

    <script>
		//Create the SVG
		var svg = d3.select("body").append("svg")
					.attr("width", 450)
					.attr("height", 400);
					
		//Put the SVG path notations into variable for easy use
		var wavyPath = "M 10,90 Q 100,15 200,70 Q 340,140 400,30",
			arcPath = "M20,300 A190,190 0 0,1 380,300";
					
		//Create an SVG wavy path		
		var path = svg.append("path")
			.attr("id", "wavy") 	//A unique ID to reference later
			.attr("d", wavyPath) 	//Notation for an SVG path
			.style("fill", "none")
			.style("stroke", "#AAAAAA")
			.style("stroke-dasharray", "5,5");

		//Create an SVG text element and append a textPath element
		var textArc = svg.append("text")
			.style("text-anchor","middle")
		  .append("textPath")				//append a textPath to the text element
			.attr("xlink:href", "#wavy") 	//place the ID of the path here
			.attr("startOffset", "50%")		//place the text halfway on the arc
			.text("My text is moving back & forth");
		
		//Transition to an arc - if you only want to transition once
		//svg.selectAll("path")
		//	.transition().duration(2000).delay(2000)
		//	.attrTween("d", pathTween(arcPath, 4));

		//Repeatedly change the arcs back and forth
		function repeat() {
			path
			  .transition().duration(2000)
			  .attrTween("d", pathTween(arcPath, 4)) 	//Transition to an arc
			  .transition().duration(2000)
			  .attrTween("d", pathTween(wavyPath, 4))	//Transition back to original arc
			  .each("end", repeat);
		}//repeat

		//Taken from //bl.ocks.org/mbostock/3916621
		function pathTween(d1, precision) {
		  return function() {
			var path0 = this,
				path1 = path0.cloneNode(),
				n0 = path0.getTotalLength(),
				n1 = (path1.setAttribute("d", d1), path1).getTotalLength();

			// Uniform sampling of distance based on specified precision.
			var distances = [0], i = 0, dt = precision / Math.max(n0, n1);
			while ((i += dt) < 1) distances.push(i);
			distances.push(1);

			// Compute point-interpolators at each distance.
			var points = distances.map(function(t) {
			  var p0 = path0.getPointAtLength(t * n0),
				  p1 = path1.getPointAtLength(t * n1);
			  return d3.interpolate([p0.x, p0.y], [p1.x, p1.y]);
			});

			return function(t) {
			  return t < 1 ? "M" + points.map(function(p) { return p(t); }).join("L") : d1;
			};
		  };
		}//pathTween
		
		repeat();
	
	</script>
	
  </body>
</html>