Skip to content

Instantly share code, notes, and snippets.

@explunit
Created July 25, 2013 18:20
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save explunit/6082362 to your computer and use it in GitHub Desktop.
Save explunit/6082362 to your computer and use it in GitHub Desktop.
Chained transitions between points on a path/line
<!DOCTYPE html>
<meta charset="utf-8">
<html>
<head>
<script src="http://d3js.org/d3.v3.min.js"></script>
</head>
<body>
<div id="line"></div>
<script type="text/javascript">
// The data for our line
var lineData = [
{x:50, y:50, speed: 0}, // there is no transition to the first element
{x:50, y:100, speed: 5000},
{x:100, y:150, speed: 1000},
{x:150, y:175, speed: 3000},
{x:225, y:175, speed: 500},
{x:275, y:200, speed: 2000},
{x:300, y:300, speed: 100},
{x:200, y:350, speed: 4000}
];
// Set the size of our graph
var w = 500;
var h = 500;
var padding = 10;
var max_x = d3.max(lineData, function(d) {return d.x;});
var max_y = d3.max(lineData, function(d) {return d.y;});
var x = d3.scale.linear().domain([0, max_x]).range([padding, (w - padding)]);
var y = d3.scale.linear().domain([0, max_y]).range([padding, (h - padding)]);
// Line generator function
var line = d3.svg.line()
.interpolate('cardinal')
.x(function(d) {return x(d.x);})
.y(function(d) {return y(d.y);})
// SVG container
var svg = d3.select('#line')
.append('svg')
.attr( { width: w, height: h, id: 'visualization' } )
// Add circles so we can see that the speed changes at the right points. Can remove later
svg.selectAll('.point')
.data(lineData)
.enter().append('circle')
.attr( {r: 4, cx: function(d) { return x(d.x); }, cy: function(d) { return y(d.y); } });
// Find the length of the line at each given point.
// Hack: draw hidden line with portion of the points -- surely there is a more elegant way but I'm not sure how to get the 'cardinal' interpolation
var lengthAt = [];
for (var i = 1; i < lineData.length - 1; i++) {
var path = svg.append('path').attr( { d: line( lineData.slice(i) ), class: 'temppath', visibility: 'hidden' } )
lengthAt.push(path.node().getTotalLength());
};
svg.selectAll('.temppath').remove();
// Add the path
var path = svg.append('path')
.attr( {d: line(lineData), stroke: "steelblue", 'stroke-width': 2, fill: 'none'} );
var totalLength = path.node().getTotalLength();
path.attr( {'stroke-dasharray': totalLength + " " + totalLength, 'stroke-dashoffset': totalLength } );
// transition will be chained from either the original path or the last transition
var transitionFrom = path;
// start at 1 since no transition needed to first point
for (var i = 1; i < lineData.length; i++) {
transitionFrom = transitionFrom.transition()
.duration(lineData[i].speed)
.ease("linear")
.attr("stroke-dashoffset", lengthAt[i-1] || 0);
};
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment