Skip to content

Instantly share code, notes, and snippets.

@mbostock mbostock/.block
Last active May 21, 2018

Embed
What would you like to do?
Path Tween
license: gpl-3.0

This example demonstrates path interpolation using SVG's getPointAtLength feature. The source path and the target path are sampled uniformly using a configurable precision in pixels (here, 4px). During the transition, the path is replaced with a piecewise linear curve, or polyline, for easier interpolation. When the transition finishes, the path is restored to the original cubic Bézier. This technique is handy because it works for any path expressible with SVG's path data mini-language.

See also the circular shape tweening example.

<!DOCTYPE html>
<svg width="960" height="500">
<path transform="translate(180,150)scale(2,2)" fill="none" stroke="black" stroke-width="1.5"></path>
</svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var d0 = "M0,0c100,0 0,100 100,100c100,0 0,-100 100,-100",
d1 = "M0,0c100,0 0,100 100,100c100,0 0,-100 100,-100c100,0 0,100 100,100";
d3.select("path")
.attr("d", d0)
.transition()
.duration(2000)
.on("start", function repeat() {
d3.active(this)
.attrTween("d", pathTween(d1, 4))
.transition()
.attrTween("d", pathTween(d0, 4))
.transition()
.on("start", repeat);
});
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;
};
};
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.