Pixeled Loader
Home
Snippets
Pixeled Loader
HTML
CSS
JS
<div id="container"></div> <div class="hint">Regenerate</div>
html, body { padding: 0; margin: 0; overflow: hidden; height: 100vh; width: 100vw; background: #1D1E22; } body { display: flex; flex-direction: column; justify-content: center; align-items: center; color: white; gap: 50px; } #container { width: 40vw; height: 40vh; }
const rand = (min, max) => Math.random() * (max - min) + min; class Pixel { constructor(x, y, color, speed, delay, delayHide, step, boundSize) { this.x = x; this.y = y; this.color = color; this.speed = rand(0.1, 0.9) * speed; this.size = 0; this.sizeStep = rand(0, 0.5); this.minSize = 0.5; this.maxSizeAvailable = boundSize || 2; this.maxSize = rand(this.minSize, this.maxSizeAvailable); this.sizeDirection = 1; this.delay = delay; this.delayHide = delayHide; this.counter = 0; this.counterHide = 0; this.counterStep = step; this.isHidden = false; this.isFlicking = false; } draw(ctx) { const centerOffset = this.maxSizeAvailable * 0.5 - this.size * 0.5; ctx.fillStyle = this.color; ctx.fillRect( this.x + centerOffset, this.y + centerOffset, this.size, this.size ); } show() { this.isHidden = false; this.counterHide = 0; if (this.counter <= this.delay) { this.counter += this.counterStep; return; } if (this.size >= this.maxSize) { this.isFlicking = true; } if (this.isFlicking) { this.flicking(); } else { this.size += this.sizeStep; } } hide() { this.counter = 0; if (this.counterHide <= this.delayHide) { this.counterHide += this.counterStep; if (this.isFlicking) { this.flicking(); } return; } this.isFlicking = false; if (this.size <= 0) { this.size = 0; this.isHidden = true; return; } else { this.size -= 0.05; } } flicking() { if (this.size >= this.maxSize) { this.sizeDirection = -1; } else if (this.size <= this.minSize) { this.sizeDirection = 1; } this.size += this.sizeDirection * this.speed; } } const canvas = document.createElement("canvas"); const container = document.querySelector("#container"); container.append(canvas); const ctx = canvas.getContext("2d"); let width, height, pixels; let request, lastTime, ticker; let animationDirection = 1; const interval = 1000 / 60; const maxTicker = 360; const getDelay = (x, y, direction) => { let dx = x - width * 0.5; let dy = direction ? y : y - height; return Math.sqrt(dx ** 2 + dy ** 2); }; const initPixels = () => { const h = Math.floor(rand(0, 360)); const colorsLen = 5; const colors = Array.from({ length: colorsLen }, (_, i) => `hsl(${Math.floor(rand(h, h + (i + 1) * 10))} 100% ${rand(50, 100)}%)` ); const gap = 6; const step = (width + height) * 0.005; const speed = rand(0.008, 0.25); const maxSize = Math.floor(gap * 0.5); pixels = []; for (let x = 0; x < width; x += gap) { for (let y = 0; y < height; y += gap) { if (x + maxSize > width || y + maxSize > height) continue; const color = colors[Math.floor(Math.random() * colorsLen)]; const delay = getDelay(x, y); const delayHide = getDelay(x, y, true); pixels.push(new Pixel(x, y, color, speed, delay, delayHide, step, maxSize)); } } }; const animate = () => { request = requestAnimationFrame(animate); const now = performance.now(); const diff = now - (lastTime || 0); if (diff < interval) return; lastTime = now - (diff % interval); ctx.clearRect(0, 0, width, height); if (ticker >= maxTicker) animationDirection = -1; else if (ticker <= 0) animationDirection = 1; let allHidden = true; pixels.forEach((pixel) => { if (animationDirection > 0) { pixel.show(); } else { pixel.hide(); allHidden = allHidden && pixel.isHidden; } pixel.draw(ctx); }); ticker += animationDirection; if (animationDirection < 0 && allHidden) { ticker = 0; } }; const resize = () => { cancelAnimationFrame(request); const rect = container.getBoundingClientRect(); width = Math.floor(rect.width); height = Math.floor(rect.height); canvas.width = width; canvas.height = height; initPixels(); ticker = 0; animate(); }; new ResizeObserver(resize).observe(container); document.addEventListener('click', resize);
Ad #1
Ad #2
Scroll to Top