124 lines
2.8 KiB
JavaScript
124 lines
2.8 KiB
JavaScript
/* eslint-disable no-extra-parens */
|
|
const PROBABILITY = 1 / 50000;
|
|
const HEIGHT = 2;
|
|
const MIN_LINE_LENGTH = 20;
|
|
const MAX_LINE_LENGTH = 300;
|
|
const SPEED = 0.4;
|
|
const APPEAR_PROBABILITY = 1;
|
|
|
|
const COLORS = [
|
|
"#000000",
|
|
"#00ff64",
|
|
"rgba(0,255,100,0.2)",
|
|
"#0064ff"
|
|
];
|
|
|
|
function randomBetween (min, max) {
|
|
return (Math.random() * (max - min)) + min;
|
|
}
|
|
|
|
export class BackgroundCanvas {
|
|
constructor (element) {
|
|
this._element = element;
|
|
this._ctx = element.getContext("2d");
|
|
this._destroyed = false;
|
|
this._animationFrameRequestID = null;
|
|
this._lines = null;
|
|
this.width = null;
|
|
this.height = null;
|
|
|
|
this._windowListeners = {
|
|
touchstart: () => {
|
|
this._isTouch = true;
|
|
},
|
|
resize: () => {
|
|
this._points = [];
|
|
this._init();
|
|
}
|
|
};
|
|
|
|
Object.entries(this._windowListeners)
|
|
.forEach(([event, listener]) => window.addEventListener(event, listener, { passive: true }));
|
|
|
|
this._init();
|
|
this._loop();
|
|
}
|
|
|
|
destroy() {
|
|
if (this._destroyed) {
|
|
throw new Error("Instance is already destroyed.");
|
|
}
|
|
|
|
this._destroyed = true;
|
|
this._element = null;
|
|
this._ctx = null;
|
|
|
|
Object.entries(this._windowListeners)
|
|
.forEach(([event, listener]) => window.removeEventListener(event, listener));
|
|
|
|
if (this._animationFrameRequestID !== null) {
|
|
cancelAnimationFrame(this._animationFrameRequestID);
|
|
}
|
|
}
|
|
|
|
get destroyed() {
|
|
return this._destroyed;
|
|
}
|
|
|
|
_init() {
|
|
this._element.width = window.innerWidth;
|
|
this._element.height = window.innerHeight;
|
|
|
|
this.width = this._element.clientWidth;
|
|
this.height = this._element.clientHeight;
|
|
|
|
while (this._lines === null || this._lines.length < 8) {
|
|
this._lines = [];
|
|
|
|
for (let x = 0; x < this.width; x += 1) {
|
|
for (let y = 0; y < this.height; y += 1) {
|
|
if (Math.random() < PROBABILITY) {
|
|
const color = Math.round(Math.random() * (COLORS.length - 1));
|
|
const length = 0;
|
|
|
|
this._lines.push({ x, y, color, length });
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
_loop() {
|
|
this._animationFrameRequestID = null;
|
|
|
|
this._draw();
|
|
|
|
if (!this._destroyed) {
|
|
requestAnimationFrame(() => this._loop());
|
|
}
|
|
}
|
|
|
|
_draw() {
|
|
// eslint-disable-next-line unicorn/prevent-abbreviations
|
|
const ctx = this._ctx;
|
|
|
|
ctx.clearRect(0, 0, this.width, this.height);
|
|
|
|
for (const line of this._lines) {
|
|
if (line.length === 0) {
|
|
if (Math.random() < APPEAR_PROBABILITY) {
|
|
line.length = randomBetween(MIN_LINE_LENGTH, MAX_LINE_LENGTH);
|
|
}
|
|
}
|
|
|
|
ctx.fillStyle = COLORS[line.color];
|
|
ctx.fillRect(line.x, line.y, line.length, HEIGHT);
|
|
|
|
line.x += SPEED;
|
|
|
|
if (line.x >= this.width) {
|
|
line.x = -line.length;
|
|
}
|
|
}
|
|
}
|
|
}
|