Last active
August 29, 2015 14:14
-
-
Save hacst/914f1abb9f28acc285fd to your computer and use it in GitHub Desktop.
Test Canvas based animation of a signal on a line
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<style> | |
body { | |
} | |
#canvas { | |
width: 100%; | |
height: 100%; | |
margin: 0px; | |
} | |
</style> | |
<head> | |
<title>Line animation test using canvas</title> | |
</head> | |
<body> | |
<canvas id="circuit"></canvas> | |
<script type="text/javascript"> | |
var px_per_ms = 0.1; | |
var lines = []; | |
function dt_next_toggle() { | |
return Math.random() * 2000; | |
} | |
var canvas = document.getElementById("circuit"); | |
function add_toggly_line(x, y, offsets) { | |
var length = 0; | |
for (var i = 0; i < offsets.length; ++i) { | |
length += offsets[i]; | |
} | |
var data = { | |
'sx': x, | |
'sy': y, | |
'offsets': offsets, | |
'impulses': [Number.NEGATIVE_INFINITY], | |
'state': false, | |
'length': length | |
}; | |
lines.push(data); | |
function toggle() { | |
data.state = !data.state; | |
data.impulses.push(window.performance.now()) | |
setTimeout(toggle, dt_next_toggle()); | |
} | |
setTimeout(toggle, dt_next_toggle()); | |
return data; | |
} | |
for (var o = 0; o < 2; ++o) { | |
for (var i = 0; i < 100; ++i) { | |
add_toggly_line(1000 - i * 10 + 5 + o * 500, i * 10 + 5, [100, 100, 100, 100], 400); | |
} | |
} | |
function dashes_for(timestamp, line) { | |
var dashes = []; | |
var cutoff = -1; | |
if (line.state == false) { | |
// If the state is false we need the first impulse to be interpreted as a gap | |
dashes.push(0); | |
} | |
var end_of_last_px = 0; | |
var max_runtime = line.length / px_per_ms; // Time for signal to traverse | |
for (var i = line.impulses.length - 1; i >= 0; --i) { | |
var dt = Math.max(0.0, timestamp - line.impulses[i]); // Workaround Chrome giving negative dt | |
if (dt > max_runtime) { | |
// Signal no longer relevant, can mark it and rest for deletion | |
cutoff = i; | |
break; | |
} | |
var till_px = dt * px_per_ms; | |
dashes.push(till_px - end_of_last_px); //TODO: Figure out of rounding here saves time | |
end_of_last_px = till_px; | |
} | |
dashes.push(line.length); // Simply make sure that whatever is at the end it extends the rest of the wire | |
if (cutoff > 50) { | |
// Amortized clean-up so we don't constantly shift the cheap vector | |
line.impulses.splice(0, cutoff + 1); | |
} | |
return dashes; | |
} | |
function pathLine(ctx, line) { | |
var x = line.sx; | |
var y = line.sy; | |
ctx.moveTo(x, y); | |
for (var j = 0; j < line.offsets.length; ++j) { | |
var offset = line.offsets[j]; | |
if (offset == 0) | |
continue; | |
if (j % 2 == 0) { | |
x += offset; | |
} else { | |
y += offset; | |
} | |
ctx.lineTo(x, y); | |
} | |
} | |
function drawFrame(timestamp) { | |
var ctx = canvas.getContext("2d"); | |
ctx.canvas.width = 2000; //window.innerWidth; // For now go fixed width | |
ctx.canvas.height = 2000; //window.innerHeight; | |
// Draw the background lines in one go | |
// Pretty sure we can save drawing those from scratch every frame quite | |
// easily. For now making it worst case is good though. | |
ctx.save(); | |
ctx.beginPath(); | |
ctx.lineWidth = 2; | |
for (var i = 0; i < lines.length; ++i) { | |
var line = lines[i]; | |
pathLine(ctx, line); | |
} | |
ctx.stroke(); | |
ctx.restore(); | |
// Now draw the animation | |
ctx.save(); | |
ctx.lineWidth = 2; | |
ctx.strokeStyle = 'red'; | |
for (var i = 0; i < lines.length; ++i) { | |
// Animate all lines | |
var line = lines[i]; | |
if (line.impulses.length == 0) // Line is steady state. Skip | |
continue; | |
ctx.beginPath(); | |
ctx.setLineDash(dashes_for(timestamp, line)); | |
pathLine(ctx, line); | |
ctx.stroke(); | |
} | |
ctx.restore(); | |
requestAnimationFrame(drawFrame); | |
} | |
requestAnimationFrame(drawFrame); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment