Interactive Reveal Mask
Home
Snippets
Interactive Reveal Mask
HTML
CSS
JS
<div class="reveal-card" id="card-viewport"> <div class="gradient-back"> <div class="tag">System Online</div> <h2 class="heading">REVEAL<br>THE MATRIX</h2> </div> <canvas id="mask-canvas"></canvas> </div>
:root { --bg: #050608; --surface: #0b0c10; --border: rgba(255, 255, 255, 0.04); } body { margin: 0; background: var(--bg); height: 100vh; display: flex; justify-content: center; align-items: center; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; user-select: none; -webkit-user-select: none; overflow: hidden; } .reveal-card { position: relative; width: 320px; height: 180px; background: var(--surface); border: 1px solid var(--border); border-radius: 24px; overflow: hidden; box-shadow: 0 40px 80px rgba(0, 0, 0, 0.7); } .gradient-back { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(135deg, #ff0055 0%, #00ffcc 50%, #3b82f6 100%); display: flex; flex-direction: column; justify-content: center; padding: 24px; box-sizing: border-box; z-index: 1; } .tag { font-size: 10px; font-weight: 800; color: #000; letter-spacing: 2px; text-transform: uppercase; opacity: 0.8; margin-bottom: 4px; } .heading { font-size: 32px; font-weight: 900; color: #000; margin: 0; letter-spacing: -1px; line-height: 1.1; } canvas { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 2; cursor: pointer; mix-blend-mode: multiply; }
const zone = document.getElementById('card-viewport'); const canvas = document.getElementById('mask-canvas'); const ctx = canvas.getContext('2d'); function init() { canvas.width = zone.clientWidth; canvas.height = zone.clientHeight; ctx.fillStyle = '#1e202b'; ctx.fillRect(0, 0, canvas.width, canvas.height); } function scratch(clientX, clientY) { const rect = canvas.getBoundingClientRect(); const x = clientX - rect.left; const y = clientY - rect.top; ctx.globalCompositeOperation = 'destination-out'; let brushGlow = ctx.createRadialGradient(x, y, 0, x, y, 25); brushGlow.addColorStop(0, 'rgba(0,0,0,1)'); brushGlow.addColorStop(1, 'rgba(0,0,0,0)'); ctx.fillStyle = brushGlow; ctx.beginPath(); ctx.arc(x, y, 25, 0, Math.PI * 2); ctx.fill(); } function selfHealLoop() { ctx.globalCompositeOperation = 'source-over'; ctx.fillStyle = 'rgba(30, 32, 43, 0.015)'; ctx.fillRect(0, 0, canvas.width, canvas.height); requestAnimationFrame(selfHealLoop); } zone.addEventListener('mousemove', (e) => scratch(e.clientX, e.clientY)); zone.addEventListener('touchmove', (e) => { scratch(e.touches[0].clientX, e.touches[0].clientY); }, { passive: true }); window.addEventListener('resize', init); init(); selfHealLoop();
Ad #1
Ad #2
Scroll to Top