D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
kafunk
Full window
Github gist
Point Along Stroke-Dash-Interpolated Path
forked from
mbostock
's block:
Point-Along-Path Interpolation
<!DOCTYPE html> <html> <meta charset="utf-8"> <head> <style> path { fill: lightblue; stroke: steelblue; stroke-width: 3px; stroke-linecap: round; } circle { stroke: darkgoldenrod; stroke-dasharray: 1 1; } </style> </head> <body> <script src="https://d3js.org/d3.v5.js"></script> <script> // DATA + VARS var points = [ [900, 440], [480, 220], [ 60, 440], [120, 40], [180, 420], [240, 80], [300, 360], [360, 120], [420, 300], [480, 160], [540, 300], [600, 120], [660, 360], [720, 80], [780, 420], [840, 40] ]; var line = d3.line().curve(d3.curveCardinalClosed.tension(0)) var origDash = "4 8 16 8"; // duration time var t = 12000; // SVG var svg = d3.select("body").append("svg") .datum(points) .attr("width", 960) .attr("height", 500); // append radial color gradient to new svg <defs> element var radialGradient = svg.append("defs").append("radialGradient") .attr("id", "radial-gradient") .attr("cx", "50%") .attr("cy", "50%") .attr("r", "75%") // define color scales var numColors = 9, gradientScale = d3.scaleLinear() .domain([0,(numColors-1)/2,numColors-1]) .range(["lightyellow","goldenrod","darkgoldenrod"]) // bind specific color stops to radialGradient radialGradient.selectAll("stop") .data(d3.range(numColors)) .enter().append("stop") .attr("offset", function(d,i) { return i/(numColors-1)*50 + 40 + "%"; }) .attr("stop-color", d => { return gradientScale(d) }); // APPEND LINE/PATH // faint underlying svg.append("path") .style("stroke", "#ddd") .style("stroke-dasharray", origDash) .attr("d", line); var path = svg.append("path") .style("stroke-dasharray", origDash) .attr("d", line) // APPEND CIRCLES/POINTS // little guys svg.selectAll(".point") .data(points) .enter().append("circle") .attr("r", 4) .style("fill","url(#radial-gradient)") .attr("transform", function(d) { return "translate(" + d + ")"; }); // big guy (in motion) var point = svg.append("circle") .attr("r", 14) .style("fill","url(#radial-gradient)") .style("stroke-width", "4") .attr("transform", "translate(" + points[0] + ")") var l = path.node().getTotalLength(); // FUNCTIONS function goPoint() { point.transition() .duration(t) .attrTween("transform", translateAlong(path.node())) .on("start", goPath) // point transition triggers path } function goPath() { path.transition() .duration(t) .styleTween("stroke-dasharray", tweenDash) .transition() .duration(t/4) .styleTween("stroke-dasharray", dashBack) .on("end", goPoint) } // functions returning interpolated stroke-dasharray value function tweenDash() { var i = d3.interpolateString("0," + l, l + "," + l); return function(t) { return i(t); }; } function dashBack() { var i = d3.interpolateString(l + ",0", "0," + l); return function(t) { return i(t); }; } // function returns value for translating point along path function translateAlong(path) { return function(d, i, a) { return function(t) { var p = path.getPointAtLength(t * l); return "translate(" + p.x + "," + p.y + ")"; } } } // INITIATE ANIMATION goPoint() </script> </body> </html>
https://d3js.org/d3.v5.js