Skip to content

Instantly share code, notes, and snippets.

Last active January 1, 2020 08:40
Show Gist options
  • Save nbremer/25e2db4abc9eaf080190 to your computer and use it in GitHub Desktop.
Save nbremer/25e2db4abc9eaf080190 to your computer and use it in GitHub Desktop.
Text on an Arc - Animate from a Wavy line to an Arc
height: 350
<!DOCTYPE html>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Text on simple Arc</title>
<!-- D3.js -->
<script src="" charset="utf-8"></script>
<!-- Google Font -->
<link href='' rel='stylesheet' type='text/css'>
body {
font-family: 'Pacifico', sans-serif;
fill: #333333;
font-size: 30px;
text-align: center;
<div id="chart"></div>
//Create the SVG
var svg ="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")
.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
// .transition().duration(2000).delay(2000)
// .attrTween("d", pathTween(arcPath, 4));
//Repeatedly change the arcs back and forth
function repeat() {
.attrTween("d", pathTween(arcPath, 4)) //Transition to an arc
.attrTween("d", pathTween(wavyPath, 4)) //Transition back to original arc
.each("end", repeat);
//Taken from
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);
// Compute point-interpolators at each distance.
var points = {
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" + { return p(t); }).join("L") : d1;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment