Built with blockbuilder.org
forked from tomshanley's block: animating dots along a path
license: mit |
Built with blockbuilder.org
forked from tomshanley's block: animating dots along a path
<!DOCTYPE html> | |
<head> | |
<meta charset="utf-8"> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<style> | |
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; } | |
path { | |
fill: none; | |
stroke: lightgrey; | |
} | |
</style> | |
</head> | |
<body> | |
<svg width="500" height="500"> | |
<g id="g-line"></g> | |
</svg> | |
<script> | |
var svg = d3.select("svg"); | |
var gap = 75; | |
var duration = 100 | |
var pathWidth = 14.14; | |
var line = d3.line() | |
.x(function(d) { return d.x; }) | |
.y(function(d) { return d.y; }) | |
//.curve(d3.curveCatmullRom.alpha(0.5)); | |
var points = [{x: 0, y: 200}, {x: 25, y: 180}, {x: 50, y: 150}, {x: 100, y: 145}, {x: 200, y: 130}, {x: 300, y: 120}, {x: 500, y: 25}]; | |
d3.select("#g-line") | |
.append("path") | |
.attr("d", line(points)) | |
.attr("id", "myPath") | |
.style("stroke-width", pathWidth) | |
.style("stroke", "red") | |
.style("opacity", 0.5) | |
var totalLength = myPath.getTotalLength(); | |
var numberOfDots = Math.floor(totalLength / gap); | |
var data = d3.range(numberOfDots).map(function(d, i) { | |
let length = myPath.getTotalLength() * (i/numberOfDots); | |
let point = myPath.getPointAtLength(length); | |
let nextLength = myPath.getTotalLength() * ((i + 1)/numberOfDots) | |
let nextPoint = myPath.getPointAtLength(nextLength); | |
//this needs much improvement!!! | |
let adj = nextPoint.x - point.x; | |
let opp = point.y - nextPoint.y; | |
let angle = Math.atan(opp/adj) * (180 / Math.PI ); | |
let rotation = 45 - angle; | |
console.log(angle) | |
//return point.x; | |
return {x: point.x, y: point.y, rotation: rotation}; | |
}); | |
var defs = svg.append("defs"); | |
let gradient = defs.append("linearGradient") | |
.attr("id", "gradient") | |
.attr("x1", 0) | |
.attr("y1", 1) | |
.attr("x2", 1) | |
.attr("y2", 0) | |
gradient.selectAll("stop") | |
.data([0,1]) | |
.enter() | |
.append("stop") | |
.attr("offset", function (d) { return (d * 100) + "%"; }) | |
.attr("stop-opacity", function (d) { return d; }) | |
.attr("stop-color", "red"); | |
var squares = svg.selectAll(".dot") | |
.data(data) | |
.enter() | |
.append("rect") | |
.attr("width", 10) | |
.attr("height", 10) | |
.attr("x", function(d, i){ return d.x - 7 ; }) | |
.attr("y",function(d, i){ return d.y - 3; }) | |
.style("fill", "url(#gradient)") | |
.attr("transform", function(d, i){ return "rotate(" + d.rotation + ","+ d.x + "," + d.y + ")"; }) | |
/*var count = 0; | |
var tid = setInterval(updateDots, duration); | |
function updateDots() { | |
squares.transition() | |
.duration(100) | |
.style("opacity", function(d,i){ | |
var opacity = 0 | |
//if at the end or near the end of the path, start from the beginning | |
if (count == numberOfDots ) { | |
if ( i == numberOfDots || i == 0 || i == 1 ) { | |
opacity = 1; | |
} else { | |
opacity = 0; | |
}; | |
} else if (count == (numberOfDots - 1) ) { | |
if ( i == numberOfDots || i == (numberOfDots - 1) || i == 0 ) { | |
opacity = 1; | |
} else { | |
opacity = 0; | |
}; | |
//else shade the 3 dots from the count onwards | |
} else { | |
if (i == count || i == (count + 1) || i == (count + 2) ) { | |
opacity = 1; | |
} else { | |
opacity = 0; | |
}; | |
}; | |
return opacity | |
}); | |
count = count == numberOfDots ? 0 : count + 1; | |
}; | |
*/ | |
</script> | |
</body> |