const howManyLines = 50;
const alwaysToEdge = true;
const minDuration = 500;
const maxDuration = 20000;
class BouncingLine {
constructor() {
this.canvas = document.getElementById('line-test');
this.start = this.randomLineCoordinates();
this.dest = this.randomLineCoordinates();
this.duration = this.randomDuration();
this.setTime();
}
now = () => new Date().valueOf();
elapsed = () => this.now() - this.startTime;
setTime = () => this.startTime = this.now();
isComplete = () => this.startTime + this.elapsed() > this.startTime + this.duration;
randomDuration = () => _.random(minDuration, maxDuration);
randomX = () => _.random(0, this.canvas.width);
randomY = () => _.random(0, this.canvas.height);
coinFlip = (heads, tails) => _.random(0, 1) === 1 ? heads : tails;
randomLineCoordinates() {
let coordinates = {
p1: { x: this.randomX(), y: this.randomY() },
p2: { x: this.randomX(), y: this.randomY() }
};
if (alwaysToEdge) {
const p = this.coinFlip('p1', 'p2');
const xY = this.coinFlip('x', 'y');
const lowerBound = 0;
const upperBound = xY === 'x' ? this.canvas.width : this.canvas.height;
coordinates[p][xY] = this.coinFlip(lowerBound, upperBound);
}
return coordinates;
}
getCurrentPosition(pointID, axis) {
const start = this.start[pointID][axis], dest = this.dest[pointID][axis]
return start + (dest - start) * this.elapsed() / this.duration;;
}
draw(clearFramePreDraw) {
const ctx = this.canvas.getContext('2d');
if (clearFramePreDraw) ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
ctx.beginPath();
ctx.moveTo(this.getCurrentPosition('p1', 'x'), this.getCurrentPosition('p1', 'y'));
ctx.lineTo(this.getCurrentPosition('p2', 'x'), this.getCurrentPosition('p2', 'y'));
ctx.closePath();
ctx.stroke();
this.update();
}
update() {
if (this.isComplete()) {
this.start = this.dest;
this.dest = this.randomLineCoordinates();
this.duration = this.randomDuration();
this.setTime();
}
}
}
const lines = _.times(howManyLines, () => new BouncingLine());
const renderFrame = () => {
_.forEach(lines, (line, i) => line.draw(i === 0 ? true : false));
window.requestAnimationFrame(renderFrame);
}
renderFrame();
<canvas id="line-test" width="500" height="210" />
#line-test {
border: 1px solid black;
}