DoubleD31/binary-whisperer-code-matrix
0
1class MatrixBackground extends HTMLElement {2 constructor() {3 super();4 this.digits = '01';5 this.streams = [];6 }7 8 connectedCallback() {9 this.attachShadow({ mode: 'open' });10 this.shadowRoot.innerHTML = `11 <style>12 :host {13 position: fixed;14 top: 0;15 left: 0;16 width: 100%;17 height: 100%;18 z-index: -1;19 pointer-events: none;20 overflow: hidden;21 opacity: 0.3;22 }23 .matrix-digit {24 position: absolute;25 color: #00b894;26 font-family: 'Fira Code', monospace;27 font-size: 14px;28 opacity: 0;29 animation: fall linear infinite;30 text-shadow: 0 0 8px rgba(0, 184, 148, 0.5);31 user-select: none;32 }33 @keyframes fall {34 0% {35 transform: translateY(-100px);36 opacity: 0;37 }38 10% {39 opacity: 0.8;40 }41 90% {42 opacity: 0.8;43 }44 100% {45 transform: translateY(100vh);46 opacity: 0;47 }48 }49 </style>50 <div id="matrix-container"></div>51 `;52 53 this.container = this.shadowRoot.getElementById('matrix-container');54 this.initMatrix();55 this.setupResizeHandler();56 }57 58 initMatrix() {59 this.container.innerHTML = '';60 this.streams = [];61 62 const columns = Math.floor(window.innerWidth / 20);63 const fontSize = 14;64 65 for (let i = 0; i < columns; i++) {66 this.createStream(i * 20, fontSize);67 }68 }69 70 createStream(x, fontSize) {71 const stream = {72 x: x,73 y: -100,74 digits: [],75 speed: Math.random() * 3000 + 2000,76 length: Math.floor(Math.random() * 15) + 5,77 nextUpdate: 078 };79 80 // Create initial digits81 for (let i = 0; i < stream.length; i++) {82 const digit = document.createElement('div');83 digit.className = 'matrix-digit';84 digit.textContent = this.digits.charAt(Math.floor(Math.random() * this.digits.length));85 digit.style.left = `${stream.x}px`;86 digit.style.top = `${stream.y - (i * fontSize)}px`;87 digit.style.animationDuration = `${stream.speed}ms`;88 digit.style.animationDelay = `${i * 100}ms`;89 digit.style.opacity = (1 - (i / stream.length)) * 0.8;90 91 this.container.appendChild(digit);92 stream.digits.push(digit);93 }94 95 this.streams.push(stream);96 }97 98 updateMatrix() {99 const now = Date.now();100 101 this.streams.forEach(stream => {102 if (now > stream.nextUpdate) {103 // Update digit positions and values104 stream.digits.forEach((digit, index) => {105 const currentTop = parseInt(digit.style.top) || (stream.y - (index * 14));106 let newTop = currentTop + 2;107 108 // Reset if off screen109 if (newTop > window.innerHeight + 100) {110 newTop = -100;111 digit.textContent = this.digits.charAt(Math.floor(Math.random() * this.digits.length));112 }113 114 digit.style.top = `${newTop}px`;115 digit.style.opacity = Math.max(0, 0.8 - (newTop / window.innerHeight) * 0.8);116 });117 118 stream.nextUpdate = now + 50; // Update every 50ms119 }120 });121 122 this.animationFrame = requestAnimationFrame(() => this.updateMatrix());123 }124 125 setupResizeHandler() {126 let resizeTimeout;127 window.addEventListener('resize', () => {128 clearTimeout(resizeTimeout);129 resizeTimeout = setTimeout(() => {130 this.initMatrix();131 }, 250);132 });133 }134 135 disconnectedCallback() {136 if (this.animationFrame) {137 cancelAnimationFrame(this.animationFrame);138 }139 }140}141 142customElements.define('matrix-background', MatrixBackground);