JSFiddle - React, Tailwind, and code Playground
by meetamit
CSS
circle {
stroke: #fff;
stroke-width: 3px;
}
path {
fill: none;
stroke: #000;
stroke-width: 3px;
}
JavaScript
var pathdata = [
[[240, 100],
[290, 200],
[340, 50]],
[[340, 50],
[90, 150],
[140, 50],
[190, 200]],
[[190, 200],
[70, 180],
[30, 30],
[350, 160]]
];
var svg = d3.select("body").append("svg")
.attr("width", 960)
.attr("height", 500);
var paths = svg.selectAll("path")
.data(pathdata)
.enter()
.append("path")
.attr("d", d3.svg.line())
.attr("id",function(d, i) { return "path" + i });
// plot path vertices
svg.selectAll(".point")
.data([].concat.apply([], pathdata))
.enter().append("circle")
.attr("r", 5)
.attr("fill", "red")
.attr("transform", function(d) { return "translate(" + d + ")"; });
// Start the first animation.
animateSinglePath(paths, 0);
function animateSinglePath(selection, indexOfAnimated) {
indexOfAnimated = indexOfAnimated || 0;
// Create circle if doesn't already exist
// (achived by binding to single element array)
circle = svg.selectAll('.animated-circle').data([null])
circle.enter()
.append("circle")
.attr("class", "animated-circle")
.attr("r", 10)
.attr("fill", "steelblue")
selection.each(function(d, i) {
if(i == indexOfAnimated) {
// In this context, the "this" object is the DOM
// element of the path whose index, i equals the
// desired indexOfAnimated
path = d3.select(this)
// For style, make it dashed
path.attr('stroke-dasharray', '5, 5')
// Move circle to start pos and begin animation
console.log('Start animation', i)
circle
.attr("transform", "translate(" + d[0] + ")")
.transition()
.duration(2000)
.attrTween("transform", translateAlong(path.node()))
.each('end', function() {
console.log('End animation', i);
// For style, revert...