JSFiddle - React, Tailwind, and code Playground
HTML
<canvas id="canvas" style="width:100vw;height:100vh"></canvas>
Babel + JSX
const canvas = document.getElementById('canvas');
canvas.setAttribute('width', document.body.clientWidth * devicePixelRatio);
canvas.setAttribute('height', document.body.clientHeight * devicePixelRatio);
const ctx = canvas.getContext('2d');
class Factory {
constructor(dir, color, interval, initialItems) {
this.dir = dir;
this.color = color;
this.interval = interval || 5000;
this.items = initialItems || [];
this.generate();
}
draw() {
this.items.forEach(item => {
item.next().draw();
});
}
generate() {
this.items.push(new Line({
ctx,
position: this.dir === 'right' ? -1 : canvas.width + 1,
amount: Math.random() * 0.5 + 0.5,
dir: this.dir,
color: this.color,
}));
}
process() {
setTimeout(() => {
this.generate();
this.process();
}, Math.random() * 1000 + this.interval);
}
}
class Line {
constructor(data) {
this.position = data.position;
this.amount = data.amount || Math.random() * 0.5 + 0.5;
this.dir = data.dir || 'right';
this.ctx = data.ctx;
this.color = data.color || '#888';
this.draw();
}
draw() {
ctx.beginPath();
ctx.strokeStyle = this.color;
ctx.lineWidth = 0.5;
ctx.moveTo(this.position, 0);
ctx.lineTo(this.position, canvas.height);
ctx.stroke();
}
next() {
if (this.dir === 'right') {
this.position = this.position + this.amount;
} else {
this.position = this.position - this.amount;
}
return this;
}
}
const rightFactory = new Factory('right', '#888', 3000, [
new Line({position: canvas.width / 2}),
new Line({position: canvas.width / 3}),
new Line({position: canvas.width / 4}),
new Line({position: canvas.width - canvas.width / 4}),
]);
const leftFactory = new Factory('left', '#ffe705', 5000, [
new Line({position: Math.random() * 300 + 150, dir: 'left', color: '#ffe705'}),
new Line({position: canvas.width - canvas.width / 3.7, dir: 'left',...