Using Path2D
and setLineDash
for better performance animating lots of lines on a <canvas>
element.
See also: Dynamic CSS line animation, Single path dasharray
Using Path2D
and setLineDash
for better performance animating lots of lines on a <canvas>
element.
See also: Dynamic CSS line animation, Single path dasharray
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<canvas width="960" height="500"></canvas> | |
<script src="//d3js.org/d3.v4.min.js"></script> | |
<script> | |
var width = 960, | |
height = 500, | |
context = document.querySelector("canvas").getContext("2d"); | |
var lines = generateLines(1000, 100).map(function(line, i){ | |
return { | |
length: getTotalLength(line), | |
path: new Path2D("M" + line.join("L")), | |
color: d3.interpolateRainbow(i / 1000) | |
}; | |
}); | |
function getTotalLength(line) { | |
var length = 0, | |
dx, | |
dy; | |
for (var i = 1; i < line.length; i++) { | |
dx = line[i][0] - line[i - 1][0]; | |
dy = line[i][1] - line[i - 1][1]; | |
length += Math.sqrt(dx * dx + dy * dy); | |
} | |
return length; | |
} | |
timer = d3.timer(function(t){ | |
var progress = 2 * Math.min(t % 3000 / 3000, 1 - t % 3000 / 3000); | |
context.clearRect(0, 0, width, height); | |
lines.forEach(function(line, i){ | |
context.strokeStyle = line.color; | |
context.setLineDash([progress * line.length, line.length]); | |
context.stroke(line.path); | |
}); | |
}); | |
function generateLines(numLines, pointsPerLine) { | |
return d3.range(numLines).map(function(i){ | |
var amplitude = ((i + 1) / numLines) * height / 2; | |
return d3.range(pointsPerLine).map(function(j){ | |
var progress = j / (pointsPerLine - 1); | |
return [progress * width, height / 2 + Math.sin(4 * Math.PI * progress) * amplitude]; | |
}); | |
}); | |
} | |
</script> |