Skip to content

Instantly share code, notes, and snippets.

@EmbraceLife
Last active July 29, 2016 15:55
Show Gist options
  • Save EmbraceLife/8b778f0bd58990d7ee97679c79536a15 to your computer and use it in GitHub Desktop.
Save EmbraceLife/8b778f0bd58990d7ee97679c79536a15 to your computer and use it in GitHub Desktop.
Line Transition 1: (Broken)
license: gpl-3.0

This example is the first of three in the Path Transitions tutorial.

When you interpolate a path element’s “d” attribute using transition.attr, the default interpolator is typically d3.interpolateString. This interpolator is not specialized for SVG paths, and instead simply looks for numbers embedded in strings. Numbers in the start and end strings are paired and then interpolated. So, the default behavior when interpolating two paths pairs numbers like this:

M x0, y0 L x1, y1 L x2, y2 L x3, y3
   ↓   ↓    ↓   ↓    ↓   ↓    ↓   ↓
M x0, y1 L x1, y2 L x2, y3 L x3, y4

The first point ⟨x0,y0⟩ is interpolated to ⟨x0,y1⟩. Since the x-values are the same for each pair of points, only the y-values change, and the path doesn’t slide left as intended.

For the correct behavior, see the next example.

forked from mbostock's block: Line Transition 1: (Broken)

<!DOCTYPE html>
<meta charset="utf-8">
<script src="//d3js.org/d3.v4.min.js"></script>
<!-- step 1: -->
<svg width="960" height="500"></svg>
<!-- step 2: -->
<style>
.line {
fill: none;
stroke: #000;
stroke-width: 1.5px;
}
</style>
<script>
// ---- step 3: inner canvas
var svg = d3.select("svg"),
margin = {top: 20, right: 20, bottom: 20, left: 40},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom,
g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// ---- step 4: scale-map for x, y
var n = 40;
var x = d3.scaleLinear()
.domain([0, n - 1])
.range([0, width]);
var y = d3.scaleLinear()
.domain([-1, 1])
.range([height, 0]);
// ---- step 5: create a line -----
var line = d3.line()
.x(function(d, i) { return x(i); })
.y(function(d, i) { return y(d); });
// ---- step 6: draw x-axis and y-axis
g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + y(0) + ")")
.call(d3.axisBottom(x));
g.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(y));
// ---- step 7: create dataset
var random = d3.randomNormal(0, .2),
data = d3.range(n).map(random);
// ---- step 8: create a path and add transition
g.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line)
.transition()
.duration(500)
.ease(d3.easeLinear)
.on("start", tick);
function tick() {
// Push a new data point onto the back.
data.push(random());
// Pop the old data point off the front.
data.shift();
// Redraw the line (with the wrong interpolation).
d3.active(this)
.attr("d", line)
.transition()
.on("start", tick);
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment