// Ported from CanvasAPI, allegedly written on 2019-08-26. (globalThis as any).canvas_2019 = function (canvas: HTMLCanvasElement) { const isStandalone = canvas.getAttribute("data-standalone") === "true"; if (isStandalone) { canvas.parentElement!.style.backgroundColor = "#121013"; } // Canvas.tsx abstract class CanvasAPI { canvas: HTMLCanvasElement; ctx: CanvasRenderingContext2D; width = 0; height = 0; private _disposed = false; private _running = false; private _last = 0; constructor(canvas: HTMLCanvasElement) { this.canvas = canvas; this.width = canvas.width = canvas.clientWidth; this.height = canvas.height = canvas.clientHeight; const ctx = this.canvas.getContext("2d"); if (!ctx) { throw new Error("Canvas2D Not Supported!"); } this.ctx = ctx; } stopRenderLoop() { this._running = false; } startRenderLoop() { if (this._disposed) return; this._running = true; this._last = performance.now(); requestAnimationFrame(this._renderLoop); } private _renderLoop = (delta: number) => { if (!this._running) return; this.render(delta - this._last); this._last = delta; requestAnimationFrame(this._renderLoop); }; abstract render(delta: number): void; } // VaultBackground.ts function addGSHelper( grad: CanvasGradient, color: string, dotOpacity: number, gradStop: number, gradOpacity: number, ) { grad.addColorStop(gradStop, `rgba(${color},${dotOpacity * gradOpacity})`); } function randAround(target: number, dist: number) { return (Math.random() - 0.5) * dist * 2 + target; } class Dot { x = Math.random() * 1.1 - 0.05; y = Math.random() / 4 + 0.9; size = Math.random() * 200 + 50; opacity = 0; opacityRandom = Math.random() / 3 + 0.3; fadeInOpacity = 1; color = `${randAround(217, 30)}, ${randAround(170, 30)}, ${ randAround(255, 20) }`; life = 0; ySpeed_1 = 0; ySpeed_2 = -0.0000063; ySpeed_3 = 0.000000016; ySpeed_4 = 0.000000000009; seed = Math.random(); delete = false; update(init: boolean) { this.life += 0.8; if (this.life < 115) { this.opacity = this.life / 230; } else if (this.life > 450) { this.delete = true; } else if (this.life > 300) { this.opacity = (150 + 300 - this.life) / 300; } this.ySpeed_3 += this.ySpeed_4; this.ySpeed_2 += this.ySpeed_3; this.ySpeed_1 += this.ySpeed_2; this.y += this.ySpeed_1 * 0.5; this.size -= 0.08; if (this.delete) { Object.assign(this, new Dot()); } } render(scene: VaultBackground) { const ctx = scene.ctx; if (this.fadeInOpacity < 1) { this.fadeInOpacity += 0.0075; } const finalX = this.x + Math.sin(this.seed * Math.PI * 2 + Date.now() / 15000) * 0.2; const drawX = scene.shakeX + finalX * Math.max(700, scene.width) - (Math.max(700, scene.width) - scene.width) / 2; const drawY = scene.shakeY + (this.y * 1.5 - 0.5) * scene.height; const opacity = this.opacity * this.opacityRandom * this.fadeInOpacity; const grad = ctx.createRadialGradient( drawX, drawY, 0, drawX, drawY, this.size, ); addGSHelper(grad, this.color, opacity, 0, 1); addGSHelper(grad, this.color, opacity, 0.8, 0.7); addGSHelper(grad, this.color, opacity, 0.87, 0.5); addGSHelper(grad, this.color, opacity, 0.93, 0.3); addGSHelper(grad, this.color, opacity, 1, 0); ctx.fillStyle = grad; ctx.fillRect( drawX - this.size, drawY - this.size, this.size * 2, this.size * 2, ); } } class VaultBackground extends CanvasAPI { private items = new Set(); private shakeVar = 0; private dom?: HTMLElement; shakeX = 0; shakeY = 0; constructor(canvas: HTMLCanvasElement) { super(canvas); for (let i = 0; i < 450; i++) { if (i % 7 === 0) { this.items.add(new Dot()); } this.items.forEach((x) => x.update(true)); } this.items.forEach((x) => x.fadeInOpacity = 0); } render(): void { this.ctx.clearRect(0, 0, this.width, this.height); this.items.forEach((x) => (x.update(false), x.render(this))); if (this.shakeVar >= 0.0001) { this.shakeVar *= 0.97 - 0.22 * this.shakeVar; if (this.shakeVar >= 0.0001) { this.shakeX = (Math.random() * 2 - 1) * this.shakeVar * 65; this.shakeY = (Math.random() * 2 - 1) * this.shakeVar * 65; if (this.dom) { this.dom.style.transform = `translate(${this.shakeX}px,${this.shakeY}px)`; } } else { this.shakeX = 0; this.shakeY = 0; if (this.dom) this.dom.style.removeProperty("transform"); this.dom = undefined; } } } shake(dom?: HTMLElement | null) { this.dom = dom || document.body; this.shakeVar = 1; } } // Binding code let bg = new VaultBackground(canvas); bg.startRenderLoop(); canvas.style.opacity = "0.2"; function onResize() { bg.width = canvas.width = canvas.clientWidth; bg.height = canvas.height = canvas.clientHeight; } window.addEventListener("resize", onResize); onResize(); (globalThis as any).vault = bg; return () => { bg.stopRenderLoop(); window.removeEventListener("resize", onResize); }; };