0xb84a…9f4a

All memos sent from and to 0xb84a…9f4a.

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <title>Smear Art</title> <style>*{margin:0;padding:0;box-sizing:border-box}body,html{width:100%;height:100%;overflow:hidden;background:#000}#container{position:relative;width:600px;height:600px;margin:0 auto;background:#000}.partition{position:absolute;overflow:hidden}.partition canvas{width:100%;height:100%;display:block;image-rendering:pixelated;image-rendering:crisp-edges;position:relative;z-index:10}</style> </head> <body> <div id="container"></div> <script> const container = document.getElementById('container'); const partitions = [{"x":-2,"y":0,"w":308,"h":600,"pattern":"random-blocks","color1":"#ceff00","color2":"#000000","cellSize":10,"speed":5,"smearAmount":2,"direction":{"dx":-1,"dy":0,"name":"left"},"enableDirectionChange":true,"directionChangeInterval":3861.3076612313293,"sourceInterval":1000,"smearMode":"replace","trailIntensity":0.85,"opacity":1},{"x":303,"y":3,"w":311,"h":605,"pattern":"cellular-automata","color1":"#f865b0","color2":"#000000","cellSize":10,"speed":5,"smearAmount":2,"direction":{"dx":1,"dy":0,"name":"right"},"enableDirectionChange":false,"directionChangeInterval":3000,"sourceInterval":1000,"smearMode":"trail","trailIntensity":0.98,"opacity":1},{"x":163,"y":-2,"w":222,"h":611,"pattern":"perlin","color1":"#f4faff","color2":"#000000","cellSize":10,"speed":5,"smearAmount":2,"direction":{"dx":-1,"dy":1,"name":"down-left"},"enableDirectionChange":true,"directionChangeInterval":2805.7492425761707,"sourceInterval":1000,"smearMode":"replace","trailIntensity":0.85,"opacity":0.81}]; class SmearPartition { constructor(config) { this.config = config; this.div = document.createElement('div'); this.div.className = 'partition'; this.div.style.left = config.x + 'px'; this.div.style.top = config.y + 'px'; this.div.style.width = config.w + 'px'; this.div.style.height = config.h + 'px'; this.canvas = document.createElement('canvas'); this.canvas.width = Math.floor(config.w); this.canvas.height = Math.floor(config.h); this.ctx = this.canvas.getContext('2d'); this.ctx.imageSmoothingEnabled = false; this.div.appendChild(this.canvas); container.appendChild(this.div); this.direction = config.direction; this.enableDirectionChange = config.enableDirectionChange || false; this.directionChangeInterval = config.directionChangeInterval || 3000; this.lastDirectionChange = 0; this.lastSourceTime = 0; this.imageData = null; this.opacity = config.opacity !== undefined ? config.opacity : 1.0; this.fgRGB = this.hexToRGB(config.color1); this.bgRGB = this.hexToRGB(config.color2 || '#000000'); this.sourceParams = this.generateSourceParams(); this.gradientCache = null; this.caState = null; this.initPattern(); this.start(); } generateSourceParams() { return { steps: 3 + Math.floor(Math.random() * 6), stripeWidth: 2 + Math.floor(Math.random() * 8), checkSize: 1 + Math.floor(Math.random() * 4), phase: 0, dashLength: 3 + Math.floor(Math.random() * 10), gapLength: 2 + Math.floor(Math.random() * 6), density: 0.05 + Math.random() * 0.25, frequency: 1 + Math.random() * 4, sinePhase: Math.random() * Math.PI * 2, seed1: Math.random() * 100, seed2: Math.random() * 100, seed3: Math.random() * 100, counter: Math.floor(Math.random() * 65536), caRule: Math.random() > 0.5 ? 30 : 110 }; } hexToRGB(hex) { const r = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); return r ? { r: parseInt(r[1], 16), g: parseInt(r[2], 16), b: parseInt(r[3], 16) } : { r: 255, g: 255, b: 255 }; } lerpColor(t) { return { r: Math.round(this.bgRGB.r + (this.fgRGB.r - this.bgRGB.r) * t), g: Math.round(this.bgRGB.g + (this.fgRGB.g - this.bgRGB.g) * t), b: Math.round(this.bgRGB.b + (this.fgRGB.b - this.bgRGB.b) * t) }; } getSourceValue(pos, length) { const t = pos / length; const cfg = this.config; switch(cfg.pattern) { case 'noise': return Math.random() > 0.5 ? this.fgRGB : this.bgRGB; case 'linear-gradient': return this.lerpColor(t); case 'stepped-gradient': const steps = this.sourceParams.steps || 5; return this.lerpColor(Math.floor(t * steps) / (steps - 1)); case 'random-gradient': if (!this.gradientCache || this.gradientCache.length !== length) { this.generateRandomGradient(length); } return this.lerpColor(this.gradientCache[pos]); case 'stripes': return (Math.floor(pos / (cfg.cellSize || 10)) % 2 === 0) ? this.fgRGB : this.bgRGB; case 'checkerboard': return ((Math.floor(pos / (cfg.cellSize || 10)) + (this.sourceParams.phase || 0)) % 2 === 0) ? this.fgRGB : this.bgRGB; case 'random-blocks': const blockIndex = Math.floor(pos / (cfg.cellSize || 10)); const blockRandom = Math.sin(blockIndex * 12.9898 + this.sourceParams.seed1) * 43758.5453; return (blockRandom - Math.floor(blockRandom)) > 0.5 ? this.fgRGB : this.bgRGB; case 'dashes': const cycle = (this.sourceParams.dashLength || 6) + (this.sourceParams.gapLength || 3); return (pos % cycle < (this.sourceParams.dashLength || 6)) ? this.fgRGB : this.bgRGB; case 'dots': return Math.random() < (this.sourceParams.density || 0.15) ? this.fgRGB : this.bgRGB; case 'sine': const sv = (Math.sin((t * (this.sourceParams.frequency || 2) * Math.PI * 2) + (this.sourceParams.sinePhase || 0)) + 1) / 2; return this.lerpColor(sv); case 'perlin': const p1 = Math.sin(t * 3.7 + this.sourceParams.seed1) * 0.5; const p2 = Math.sin(t * 7.3 + this.sourceParams.seed2) * 0.25; const p3 = Math.sin(t * 13.1 + this.sourceParams.seed3) * 0.125; return this.lerpColor(Math.max(0, Math.min(1, (p1 + p2 + p3 + 0.875) / 1.75))); case 'binary-counter': return ((this.sourceParams.counter >> (pos % 16)) & 1) ? this.fgRGB : this.bgRGB; case 'cellular-automata': if (!this.caState || this.caState.length !== length) { this.initCellularAutomata(length); } return this.caState[pos] ? this.fgRGB : this.bgRGB; default: return Math.random() > 0.5 ? this.fgRGB : this.bgRGB; } } generateRandomGradient(length) { const np = 3 + Math.floor(Math.random() * 4); const cp = [0]; for (let i = 1; i < np - 1; i++) cp.push(Math.random()); cp.push(1); cp.sort((a, b) => a - b); const cv = cp.map(() => Math.random()); this.gradientCache = []; for (let i = 0; i < length; i++) { const t = i / length; let si = 0; for (let j = 0; j < cp.length - 1; j++) { if (t >= cp[j] && t <= cp[j + 1]) { si = j; break; } } const st = (t - cp[si]) / (cp[si + 1] - cp[si]); this.gradientCache.push(cv[si] + (cv[si + 1] - cv[si]) * st); } } initCellularAutomata(length) { this.caState = []; for (let i = 0; i < length; i++) { this.caState.push(Math.random() > 0.5); } } evolveCellularAutomata() { if (!this.caState) return; const rule = this.sourceParams.caRule || 30; const os = [...this.caState]; const len = this.caState.length; for (let i = 0; i < len; i++) { const p = (os[(i - 1 + len) % len] ? 4 : 0) + (os[i] ? 2 : 0) + (os[(i + 1) % len] ? 1 : 0); this.caState[i] = ((rule >> p) & 1) === 1; } } updateSourceParams() { const cfg = this.config; switch(cfg.pattern) { case 'checkerboard': this.sourceParams.phase = (this.sourceParams.phase + 1) % 2; break; case 'sine': this.sourceParams.sinePhase += 0.5; break; case 'binary-counter': this.sourceParams.counter++; break; case 'cellular-automata': this.evolveCellularAutomata(); break; case 'random-gradient': this.gradientCache = null; break; case 'perlin': this.sourceParams.seed1 += 0.3; this.sourceParams.seed2 += 0.2; this.sourceParams.seed3 += 0.1; break; } } generateSourceEdge() { this.updateSourceParams(); const data = this.imageData.data; const w = this.canvas.width; const h = this.canvas.height; const length = w; const cfg = this.config; for (let i = 0; i < length; i++) { const x = i; const y = 0; // top edge let color; // 2D patterns need both x and y coordinates if (cfg.pattern === 'checkerboard') { const cellX = Math.floor(x / (cfg.cellSize || 10)); const cellY = Math.floor(y / (cfg.cellSize || 10)); color = ((cellX + cellY) % 2 === 0) ? this.fgRGB : this.bgRGB; } else if (cfg.pattern === 'random-blocks') { const cellX = Math.floor(x / (cfg.cellSize || 10)); const cellY = Math.floor(y / (cfg.cellSize || 10)); const seed = cellX * 73856093 ^ cellY * 19349663; const blockRandom = Math.sin(seed + this.sourceParams.seed1) * 43758.5453; color = (blockRandom - Math.floor(blockRandom)) > 0.5 ? this.fgRGB : this.bgRGB; } else { // 1D patterns color = this.getSourceValue(i, length); } const idx = i * 4; data[idx] = color.r; data[idx + 1] = color.g; data[idx + 2] = color.b; data[idx + 3] = Math.round(this.opacity * 255); } } changeDirection() { const dirs = [ { dx: 0, dy: 1, name: 'down' }, { dx: 1, dy: 1, name: 'down-right' }, { dx: 1, dy: 0, name: 'right' }, { dx: 1, dy: -1, name: 'up-right' }, { dx: 0, dy: -1, name: 'up' }, { dx: -1, dy: -1, name: 'up-left' }, { dx: -1, dy: 0, name: 'left' }, { dx: -1, dy: 1, name: 'down-left' } ]; const currentIndex = dirs.findIndex(d => d.dx === this.direction.dx && d.dy === this.direction.dy); if (currentIndex === -1) return; const newIndex = Math.random() > 0.5 ? (currentIndex + 1) % 8 : (currentIndex + 7) % 8; this.direction = dirs[newIndex]; } initPattern() { const w = this.canvas.width; const h = this.canvas.height; const length = w; const cfg = this.config; this.imageData = this.ctx.createImageData(w, h); for (let y = 0; y < h; y++) { for (let x = 0; x < w; x++) { let color; // 2D patterns need both x and y if (cfg.pattern === 'checkerboard') { const cellX = Math.floor(x / (cfg.cellSize || 10)); const cellY = Math.floor(y / (cfg.cellSize || 10)); color = ((cellX + cellY) % 2 === 0) ? this.fgRGB : this.bgRGB; } else if (cfg.pattern === 'random-blocks') { const cellX = Math.floor(x / (cfg.cellSize || 10)); const cellY = Math.floor(y / (cfg.cellSize || 10)); const seed = cellX * 73856093 ^ cellY * 19349663; const blockRandom = Math.sin(seed + this.sourceParams.seed1) * 43758.5453; color = (blockRandom - Math.floor(blockRandom)) > 0.5 ? this.fgRGB : this.bgRGB; } else { // 1D patterns color = this.getSourceValue(x, length); } const idx = (y * w + x) * 4; this.imageData.data[idx] = color.r; this.imageData.data[idx + 1] = color.g; this.imageData.data[idx + 2] = color.b; this.imageData.data[idx + 3] = Math.round(this.opacity * 255); } } this.ctx.putImageData(this.imageData, 0, 0); } smear() { if (!this.imageData) return; const cfg = this.config; const data = this.imageData.data; const w = this.canvas.width; const h = this.canvas.height; const newData = this.ctx.createImageData(w, h); const newPixels = newData.data; const mode = cfg.smearMode || 'replace'; const intensity = cfg.trailIntensity || 0.85; for (let y = 0; y < h; y++) { for (let x = 0; x < w; x++) { let srcX = x - this.direction.dx * cfg.smearAmount; let srcY = y - this.direction.dy * cfg.smearAmount; srcX = (srcX + w) % w; srcY = (srcY + h) % h; const srcIdx = (srcY * w + srcX) * 4; const dstIdx = (y * w + x) * 4; if (mode === 'trail') { newPixels[dstIdx] = data[srcIdx] * intensity + data[dstIdx] * (1 - intensity); newPixels[dstIdx + 1] = data[srcIdx + 1] * intensity + data[dstIdx + 1] * (1 - intensity); newPixels[dstIdx + 2] = data[srcIdx + 2] * intensity + data[dstIdx + 2] * (1 - intensity); newPixels[dstIdx + 3] = Math.round(this.opacity * 255); } else { newPixels[dstIdx] = data[srcIdx]; newPixels[dstIdx + 1] = data[srcIdx + 1]; newPixels[dstIdx + 2] = data[srcIdx + 2]; newPixels[dstIdx + 3] = Math.round(this.opacity * 255); } } } this.imageData = newData; this.ctx.putImageData(this.imageData, 0, 0); } start() { const animate = (timestamp) => { if (!this.lastDirectionChange) this.lastDirectionChange = timestamp; if (!this.lastSourceTime) this.lastSourceTime = timestamp; if (this.enableDirectionChange && timestamp - this.lastDirectionChange >= this.directionChangeInterval) { this.changeDirection(); this.lastDirectionChange = timestamp; this.directionChangeInterval = 1000 + Math.random() * 4000; } if (timestamp - this.lastSourceTime >= (this.config.sourceInterval || 1000)) { this.generateSourceEdge(); this.lastSourceTime = timestamp; } this.smear(); setTimeout(() => requestAnimationFrame(animate), 1000 / this.config.speed); }; requestAnimationFrame(animate); } } partitions.forEach(config => new SmearPartition(config)); </script> </body> </html>
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <title>Smear Art</title> <style>*{margin:0;padding:0;box-sizing:border-box}body,html{width:100%;height:100%;overflow:hidden;background:#000}#container{position:relative;width:600px;height:600px;margin:0 auto;background:#000}.partition{position:absolute;overflow:hidden}.partition canvas{width:100%;height:100%;display:block;image-rendering:pixelated;image-rendering:crisp-edges;position:relative;z-index:10}</style> </head> <body> <div id="container"></div> <script> const container = document.getElementById('container'); const partitions = [{"x":-2,"y":0,"w":308,"h":600,"pattern":"random-blocks","color1":"#ceff00","color2":"#000000","cellSize":10,"speed":5,"smearAmount":2,"direction":{"dx":-1,"dy":0,"name":"left"},"enableDirectionChange":true,"directionChangeInterval":3861.3076612313293,"sourceInterval":1000,"smearMode":"replace","trailIntensity":0.85,"opacity":1},{"x":303,"y":3,"w":311,"h":605,"pattern":"cellular-automata","color1":"#f865b0","color2":"#000000","cellSize":10,"speed":5,"smearAmount":2,"direction":{"dx":1,"dy":0,"name":"right"},"enableDirectionChange":false,"directionChangeInterval":3000,"sourceInterval":1000,"smearMode":"trail","trailIntensity":0.98,"opacity":1},{"x":163,"y":-2,"w":222,"h":611,"pattern":"perlin","color1":"#f4faff","color2":"#000000","cellSize":10,"speed":5,"smearAmount":2,"direction":{"dx":-1,"dy":1,"name":"down-left"},"enableDirectionChange":true,"directionChangeInterval":2805.7492425761707,"sourceInterval":1000,"smearMode":"replace","trailIntensity":0.85,"opacity":0.81}]; class SmearPartition { constructor(config) { this.config = config; this.div = document.createElement('div'); this.div.className = 'partition'; this.div.style.left = config.x + 'px'; this.div.style.top = config.y + 'px'; this.div.style.width = config.w + 'px'; this.div.style.height = config.h + 'px'; this.canvas = document.createElement('canvas'); this.canvas.width = Math.floor(config.w); this.canvas.height = Math.floor(config.h); this.ctx = this.canvas.getContext('2d'); this.ctx.imageSmoothingEnabled = false; this.div.appendChild(this.canvas); container.appendChild(this.div); this.direction = config.direction; this.enableDirectionChange = config.enableDirectionChange || false; this.directionChangeInterval = config.directionChangeInterval || 3000; this.lastDirectionChange = 0; this.lastSourceTime = 0; this.imageData = null; this.opacity = config.opacity !== undefined ? config.opacity : 1.0; this.fgRGB = this.hexToRGB(config.color1); this.bgRGB = this.hexToRGB(config.color2 || '#000000'); this.sourceParams = this.generateSourceParams(); this.gradientCache = null; this.caState = null; this.initPattern(); this.start(); } generateSourceParams() { return { steps: 3 + Math.floor(Math.random() * 6), stripeWidth: 2 + Math.floor(Math.random() * 8), checkSize: 1 + Math.floor(Math.random() * 4), phase: 0, dashLength: 3 + Math.floor(Math.random() * 10), gapLength: 2 + Math.floor(Math.random() * 6), density: 0.05 + Math.random() * 0.25, frequency: 1 + Math.random() * 4, sinePhase: Math.random() * Math.PI * 2, seed1: Math.random() * 100, seed2: Math.random() * 100, seed3: Math.random() * 100, counter: Math.floor(Math.random() * 65536), caRule: Math.random() > 0.5 ? 30 : 110 }; } hexToRGB(hex) { const r = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); return r ? { r: parseInt(r[1], 16), g: parseInt(r[2], 16), b: parseInt(r[3], 16) } : { r: 255, g: 255, b: 255 }; } lerpColor(t) { return { r: Math.round(this.bgRGB.r + (this.fgRGB.r - this.bgRGB.r) * t), g: Math.round(this.bgRGB.g + (this.fgRGB.g - this.bgRGB.g) * t), b: Math.round(this.bgRGB.b + (this.fgRGB.b - this.bgRGB.b) * t) }; } getSourceValue(pos, length) { const t = pos / length; const cfg = this.config; switch(cfg.pattern) { case 'noise': return Math.random() > 0.5 ? this.fgRGB : this.bgRGB; case 'linear-gradient': return this.lerpColor(t); case 'stepped-gradient': const steps = this.sourceParams.steps || 5; return this.lerpColor(Math.floor(t * steps) / (steps - 1)); case 'random-gradient': if (!this.gradientCache || this.gradientCache.length !== length) { this.generateRandomGradient(length); } return this.lerpColor(this.gradientCache[pos]); case 'stripes': return (Math.floor(pos / (cfg.cellSize || 10)) % 2 === 0) ? this.fgRGB : this.bgRGB; case 'checkerboard': return ((Math.floor(pos / (cfg.cellSize || 10)) + (this.sourceParams.phase || 0)) % 2 === 0) ? this.fgRGB : this.bgRGB; case 'random-blocks': const blockIndex = Math.floor(pos / (cfg.cellSize || 10)); const blockRandom = Math.sin(blockIndex * 12.9898 + this.sourceParams.seed1) * 43758.5453; return (blockRandom - Math.floor(blockRandom)) > 0.5 ? this.fgRGB : this.bgRGB; case 'dashes': const cycle = (this.sourceParams.dashLength || 6) + (this.sourceParams.gapLength || 3); return (pos % cycle < (this.sourceParams.dashLength || 6)) ? this.fgRGB : this.bgRGB; case 'dots': return Math.random() < (this.sourceParams.density || 0.15) ? this.fgRGB : this.bgRGB; case 'sine': const sv = (Math.sin((t * (this.sourceParams.frequency || 2) * Math.PI * 2) + (this.sourceParams.sinePhase || 0)) + 1) / 2; return this.lerpColor(sv); case 'perlin': const p1 = Math.sin(t * 3.7 + this.sourceParams.seed1) * 0.5; const p2 = Math.sin(t * 7.3 + this.sourceParams.seed2) * 0.25; const p3 = Math.sin(t * 13.1 + this.sourceParams.seed3) * 0.125; return this.lerpColor(Math.max(0, Math.min(1, (p1 + p2 + p3 + 0.875) / 1.75))); case 'binary-counter': return ((this.sourceParams.counter >> (pos % 16)) & 1) ? this.fgRGB : this.bgRGB; case 'cellular-automata': if (!this.caState || this.caState.length !== length) { this.initCellularAutomata(length); } return this.caState[pos] ? this.fgRGB : this.bgRGB; default: return Math.random() > 0.5 ? this.fgRGB : this.bgRGB; } } generateRandomGradient(length) { const np = 3 + Math.floor(Math.random() * 4); const cp = [0]; for (let i = 1; i < np - 1; i++) cp.push(Math.random()); cp.push(1); cp.sort((a, b) => a - b); const cv = cp.map(() => Math.random()); this.gradientCache = []; for (let i = 0; i < length; i++) { const t = i / length; let si = 0; for (let j = 0; j < cp.length - 1; j++) { if (t >= cp[j] && t <= cp[j + 1]) { si = j; break; } } const st = (t - cp[si]) / (cp[si + 1] - cp[si]); this.gradientCache.push(cv[si] + (cv[si + 1] - cv[si]) * st); } } initCellularAutomata(length) { this.caState = []; for (let i = 0; i < length; i++) { this.caState.push(Math.random() > 0.5); } } evolveCellularAutomata() { if (!this.caState) return; const rule = this.sourceParams.caRule || 30; const os = [...this.caState]; const len = this.caState.length; for (let i = 0; i < len; i++) { const p = (os[(i - 1 + len) % len] ? 4 : 0) + (os[i] ? 2 : 0) + (os[(i + 1) % len] ? 1 : 0); this.caState[i] = ((rule >> p) & 1) === 1; } } updateSourceParams() { const cfg = this.config; switch(cfg.pattern) { case 'checkerboard': this.sourceParams.phase = (this.sourceParams.phase + 1) % 2; break; case 'sine': this.sourceParams.sinePhase += 0.5; break; case 'binary-counter': this.sourceParams.counter++; break; case 'cellular-automata': this.evolveCellularAutomata(); break; case 'random-gradient': this.gradientCache = null; break; case 'perlin': this.sourceParams.seed1 += 0.3; this.sourceParams.seed2 += 0.2; this.sourceParams.seed3 += 0.1; break; } } generateSourceEdge() { this.updateSourceParams(); const data = this.imageData.data; const w = this.canvas.width; const h = this.canvas.height; const length = w; const cfg = this.config; for (let i = 0; i < length; i++) { const x = i; const y = 0; // top edge let color; // 2D patterns need both x and y coordinates if (cfg.pattern === 'checkerboard') { const cellX = Math.floor(x / (cfg.cellSize || 10)); const cellY = Math.floor(y / (cfg.cellSize || 10)); color = ((cellX + cellY) % 2 === 0) ? this.fgRGB : this.bgRGB; } else if (cfg.pattern === 'random-blocks') { const cellX = Math.floor(x / (cfg.cellSize || 10)); const cellY = Math.floor(y / (cfg.cellSize || 10)); const seed = cellX * 73856093 ^ cellY * 19349663; const blockRandom = Math.sin(seed + this.sourceParams.seed1) * 43758.5453; color = (blockRandom - Math.floor(blockRandom)) > 0.5 ? this.fgRGB : this.bgRGB; } else { // 1D patterns color = this.getSourceValue(i, length); } const idx = i * 4; data[idx] = color.r; data[idx + 1] = color.g; data[idx + 2] = color.b; data[idx + 3] = Math.round(this.opacity * 255); } } changeDirection() { const dirs = [ { dx: 0, dy: 1, name: 'down' }, { dx: 1, dy: 1, name: 'down-right' }, { dx: 1, dy: 0, name: 'right' }, { dx: 1, dy: -1, name: 'up-right' }, { dx: 0, dy: -1, name: 'up' }, { dx: -1, dy: -1, name: 'up-left' }, { dx: -1, dy: 0, name: 'left' }, { dx: -1, dy: 1, name: 'down-left' } ]; const currentIndex = dirs.findIndex(d => d.dx === this.direction.dx && d.dy === this.direction.dy); if (currentIndex === -1) return; const newIndex = Math.random() > 0.5 ? (currentIndex + 1) % 8 : (currentIndex + 7) % 8; this.direction = dirs[newIndex]; } initPattern() { const w = this.canvas.width; const h = this.canvas.height; const length = w; const cfg = this.config; this.imageData = this.ctx.createImageData(w, h); for (let y = 0; y < h; y++) { for (let x = 0; x < w; x++) { let color; // 2D patterns need both x and y if (cfg.pattern === 'checkerboard') { const cellX = Math.floor(x / (cfg.cellSize || 10)); const cellY = Math.floor(y / (cfg.cellSize || 10)); color = ((cellX + cellY) % 2 === 0) ? this.fgRGB : this.bgRGB; } else if (cfg.pattern === 'random-blocks') { const cellX = Math.floor(x / (cfg.cellSize || 10)); const cellY = Math.floor(y / (cfg.cellSize || 10)); const seed = cellX * 73856093 ^ cellY * 19349663; const blockRandom = Math.sin(seed + this.sourceParams.seed1) * 43758.5453; color = (blockRandom - Math.floor(blockRandom)) > 0.5 ? this.fgRGB : this.bgRGB; } else { // 1D patterns color = this.getSourceValue(x, length); } const idx = (y * w + x) * 4; this.imageData.data[idx] = color.r; this.imageData.data[idx + 1] = color.g; this.imageData.data[idx + 2] = color.b; this.imageData.data[idx + 3] = Math.round(this.opacity * 255); } } this.ctx.putImageData(this.imageData, 0, 0); } smear() { if (!this.imageData) return; const cfg = this.config; const data = this.imageData.data; const w = this.canvas.width; const h = this.canvas.height; const newData = this.ctx.createImageData(w, h); const newPixels = newData.data; const mode = cfg.smearMode || 'replace'; const intensity = cfg.trailIntensity || 0.85; for (let y = 0; y < h; y++) { for (let x = 0; x < w; x++) { let srcX = x - this.direction.dx * cfg.smearAmount; let srcY = y - this.direction.dy * cfg.smearAmount; srcX = (srcX + w) % w; srcY = (srcY + h) % h; const srcIdx = (srcY * w + srcX) * 4; const dstIdx = (y * w + x) * 4; if (mode === 'trail') { newPixels[dstIdx] = data[srcIdx] * intensity + data[dstIdx] * (1 - intensity); newPixels[dstIdx + 1] = data[srcIdx + 1] * intensity + data[dstIdx + 1] * (1 - intensity); newPixels[dstIdx + 2] = data[srcIdx + 2] * intensity + data[dstIdx + 2] * (1 - intensity); newPixels[dstIdx + 3] = Math.round(this.opacity * 255); } else { newPixels[dstIdx] = data[srcIdx]; newPixels[dstIdx + 1] = data[srcIdx + 1]; newPixels[dstIdx + 2] = data[srcIdx + 2]; newPixels[dstIdx + 3] = Math.round(this.opacity * 255); } } } this.imageData = newData; this.ctx.putImageData(this.imageData, 0, 0); } start() { const animate = (timestamp) => { if (!this.lastDirectionChange) this.lastDirectionChange = timestamp; if (!this.lastSourceTime) this.lastSourceTime = timestamp; if (this.enableDirectionChange && timestamp - this.lastDirectionChange >= this.directionChangeInterval) { this.changeDirection(); this.lastDirectionChange = timestamp; this.directionChangeInterval = 1000 + Math.random() * 4000; } if (timestamp - this.lastSourceTime >= (this.config.sourceInterval || 1000)) { this.generateSourceEdge(); this.lastSourceTime = timestamp; } this.smear(); setTimeout(() => requestAnimationFrame(animate), 1000 / this.config.speed); }; requestAnimationFrame(animate); } } partitions.forEach(config => new SmearPartition(config)); </script> </body> </html>
<!doctype html><html><head><meta charset="utf-8"><title>shards</title><style> :root { /* Pattern 1: 7 bands */ --color1: #bb44dd; --color2: #000; --pos1: 0%; --pos2: 8.33%; --pos3: 25%; --pos4: 41.67%; --pos5: 58.33%; --pos6: 75%; --pos7: 91.67%; /* Pattern 2: 5 bands */ --color2-1: #6486f5; --color2-2: #000; --pos2-1: 0%; --pos2-2: 12.5%; --pos2-3: 37.5%; --pos2-4: 62.5%; --pos2-5: 87.5%; /* Pattern 3: 3 bands */ --color3-1: #ffffff; --color3-2: #000; --color4-1: #ff00cc; --color4-2: #000; --pos3-1: 0%; --pos3-2: 50%; --pos3-3: 100%; } body { background-color: black; margin: 0; padding: 0; width: 100vw; height: 100vh; overflow: hidden; } .gradient-container { position: absolute; overflow: hidden; transition: all 0.3s ease; clip-path: var(--clip-path); /* Emboss effect */ box-shadow: inset 2px 2px 5px rgba(255, 255, 255, 0.4), inset -2px -2px 5px rgba(0, 0, 0, 0.4); /* Add more depth with a subtle border */ } .gradient-up { background-image: repeating-linear-gradient( to bottom, var(--color1) var(--pos1), var(--color2) var(--pos2), var(--color1) var(--pos3), var(--color2) var(--pos4), var(--color1) var(--pos5), var(--color2) var(--pos6), var(--color1) var(--pos7) ); animation: moveUpwards 5s linear infinite; } .gradient-down { background-image: repeating-linear-gradient( to bottom, var(--color2-1) var(--pos2-1), var(--color2-2) var(--pos2-2), var(--color2-1) var(--pos2-3), var(--color2-2) var(--pos2-4), var(--color2-1) var(--pos2-5) ); animation: moveDownwards 5s linear infinite; } .gradient-left { background-image: repeating-linear-gradient( to right, var(--color3-1) var(--pos3-1), var(--color3-2) var(--pos3-2), var(--color3-1) var(--pos3-3) ); animation: moveLeft 5s linear infinite; } .gradient-right { background-image: repeating-linear-gradient( to right, var(--color4-1) var(--pos1), var(--color4-2) var(--pos2), var(--color4-1) var(--pos3), var(--color4-2) var(--pos4), var(--color4-1) var(--pos5), var(--color4-2) var(--pos6), var(--color4-1) var(--pos7) ); animation: moveRight 5s linear infinite; } .strobe { background-color: #000; } @keyframes strobeEffect { 0% { opacity: 0; } 100% { opacity: 1; } } @keyframes moveUpwards { 0% { background-position: 0 100%; } 100% { background-position: 0 -100%; } } @keyframes moveDownwards { 0% { background-position: 0 -100%; } 100% { background-position: 0 100%; } } @keyframes moveLeft { 0% { background-position: 100% 0; } 100% { background-position: -100% 0; } } @keyframes moveRight { 0% { background-position: -100% 0; } 100% { background-position: 100% 0; } } :root{--color1:#B4ff00;--color2:#000;--pos1:0%;--pos2:8.33%;--pos3:25%;--pos4:41.67%;--pos5:58.33%;--pos6:75%;--pos7:91.67%;--color2-1:#241a17;--color2-2:#000;--pos2-1:0%;--pos2-2:12.5%;--pos2-3:37.5%;--pos2-4:62.5%;--pos2-5:87.5%;--color3-1:#400026;--color3-2:#000;--color4-1:#241a17;--color4-2:#000;--pos3-1:0%;--pos3-2:50%;--pos3-3:100%;}:root{--color1: #B4ff00; --color2-1: #241a17; --color3-1: #400026; --color4-1: #241a17;}</style></head><body style="margin:0;background-color:black;width:100vw;height:100vh;overflow:hidden;"><div id="puzzle-container"><div class="gradient-container gradient-down" data-x="0" data-y="0" data-width="0.43679999999999997" data-height="0.05" style="left: 0px; top: 0px; width: 284.794px; height: 32.6px; --clip-path: polygon(0% 0%, 92% 0%, 103% 256%, 0% 223%); background-size: 284.794px 65.2px; animation-duration: 18s;"></div><div class="gradient-container gradient-down" data-x="0.43679999999999997" data-y="0" data-width="0.40319999999999995" data-height="0.05" style="left: 284.794px; top: 0px; width: 262.886px; height: 32.6px; --clip-path: polygon(-9% 0%, 98% 0%, 82% -59%, 3% 256%); background-size: 262.886px 65.2px; animation-duration: 30s;"></div><div class="gradient-container gradient-up" data-x="0.84" data-y="0" data-width="0.1600000000000001" data-height="0.05" style="left: 547.68px; top: 0px; width: 104.32px; height: 32.6px; --clip-path: polygon(-4% 0%, 100% 0%, 100% 8%, -44% -59%); background-size: 104.32px 65.2px; animation-duration: 1s;"></div><div class="gradient-container gradient-left" data-x="0" data-y="0.05" data-width="0.15" data-height="0.95" style="left: 0px; top: 32.6px; width: 97.8px; height: 619.4px; --clip-path: polygon(0% 6%, 117% 6%, 47% 100%, 0% 100%); background-size: 195.6px 619.4px; animation-duration: 26s;"></div><div class="gradient-container gradient-up" data-x="0.15" data-y="0.05" data-width="0.8500000000000001" data-height="0.95" style="left: 97.8px; top: 32.6px; width: 554.2px; height: 619.4px; --clip-path: polygon(3% 6%, 100% -5%, 100% 100%, -9% 100%); background-size: 554.2px 1238.8px; animation-duration: 81s;"></div></div><script>function layoutShards(){var vw=window.innerWidth;var vh=window.innerHeight;document.querySelectorAll(".gradient-container").forEach(function(div){var x=parseFloat(div.dataset.x||0);var y=parseFloat(div.dataset.y||0);var w=parseFloat(div.dataset.width||0);var h=parseFloat(div.dataset.height||0);div.style.left=(x*vw)+"px";div.style.top=(y*vh)+"px";div.style.width=(w*vw)+"px";div.style.height=(h*vh)+"px";if(div.classList.contains("gradient-left")||div.classList.contains("gradient-right")){div.style.backgroundSize=(w*vw*2)+"px "+(h*vh)+"px";}else{div.style.backgroundSize=(w*vw)+"px "+(h*vh*2)+"px";}});}window.addEventListener("resize",layoutShards);window.addEventListener("load",layoutShards);layoutShards();</script></body></html>
<!doctype html><html><head><meta charset="utf-8"><title>smear</title><style> * { margin: 0; padding: 0; box-sizing: border-box; } body, html { width: 100%; height: 100%; overflow: hidden; background: #000; } smear-partition { display: block; width: 100%; height: 100%; position: relative; } smear-canvas { display: block; position: absolute; } smear-canvas canvas { display: block; width: 100%; height: 100%; image-rendering: pixelated; image-rendering: -moz-crisp-edges; image-rendering: crisp-edges; -ms-interpolation-mode: nearest-neighbor; } .smear-container { position: absolute; overflow: hidden; } .smear-container canvas { display: block; width: 100%; height: 100%; image-rendering: pixelated; image-rendering: crisp-edges; } </style></head><body style="margin:0;background-color:black;width:100vw;height:100vh;overflow:hidden;"><div id="puzzle-container"><div class="smear-container" data-x="0" data-y="0" data-width="1" data-height="0.015733128834355826" data-start-edge="right" data-speed="89" data-source-interval="1923" data-pixel-size="1" data-color-fg="#FF8000" data-color-bg="#FFFFFF" data-source-type="noise" style="left: 0px; top: 0px; width: 652px; height: 10.258px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.015733128834355826" data-width="1" data-height="0.028207208588957058" data-start-edge="bottom" data-speed="97" data-source-interval="1287" data-pixel-size="2" data-color-fg="#FF8000" data-color-bg="#FFFFFF" data-source-type="noise" style="left: 0px; top: 10.258px; width: 652px; height: 18.3911px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.04394033742331289" data-width="1" data-height="0.025200920245398776" data-start-edge="right" data-speed="25" data-source-interval="650" data-pixel-size="1" data-color-fg="#800080" data-color-bg="#000000" data-source-type="noise" style="left: 0px; top: 28.6491px; width: 652px; height: 16.431px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.06914125766871165" data-width="1" data-height="0.044004294478527606" data-start-edge="top" data-speed="58" data-source-interval="1276" data-pixel-size="1" data-color-fg="#FF8000" data-color-bg="#FFFFFF" data-source-type="noise" style="left: 0px; top: 45.0801px; width: 652px; height: 28.6908px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.11314555214723926" data-width="1" data-height="0.0287680981595092" data-start-edge="top" data-speed="48" data-source-interval="1737" data-pixel-size="4" data-color-fg="#800080" data-color-bg="#000000" data-source-type="noise" style="left: 0px; top: 73.7709px; width: 652px; height: 18.7568px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.14191365030674846" data-width="1" data-height="0.036271932515337425" data-start-edge="bottom" data-speed="48" data-source-interval="1897" data-pixel-size="5" data-color-fg="#FF8000" data-color-bg="#FFFFFF" data-source-type="noise" style="left: 0px; top: 92.5277px; width: 652px; height: 23.6493px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.1781855828220859" data-width="1" data-height="0.02023251533742331" data-start-edge="bottom" data-speed="63" data-source-interval="1627" data-pixel-size="2" data-color-fg="#800080" data-color-bg="#000000" data-source-type="noise" style="left: 0px; top: 116.177px; width: 652px; height: 13.1916px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.1984187116564417" data-width="1" data-height="0.032433128834355826" data-start-edge="top" data-speed="62" data-source-interval="1221" data-pixel-size="6" data-color-fg="#FF8000" data-color-bg="#FFFFFF" data-source-type="noise" style="left: 0px; top: 129.369px; width: 652px; height: 21.1464px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.230851226993865" data-width="1" data-height="0.02615966257668712" data-start-edge="left" data-speed="36" data-source-interval="541" data-pixel-size="6" data-color-fg="#FF8000" data-color-bg="#FFFFFF" data-source-type="noise" style="left: 0px; top: 150.515px; width: 652px; height: 17.0561px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.25701073619631903" data-width="1" data-height="0.011631978527607362" data-start-edge="left" data-speed="92" data-source-interval="1868" data-pixel-size="2" data-color-fg="#800080" data-color-bg="#000000" data-source-type="noise" style="left: 0px; top: 167.571px; width: 652px; height: 7.58405px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.2686426380368098" data-width="1" data-height="0.038517791411042945" data-start-edge="left" data-speed="39" data-source-interval="1068" data-pixel-size="2" data-color-fg="#800080" data-color-bg="#000000" data-source-type="noise" style="left: 0px; top: 175.155px; width: 652px; height: 25.1136px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.3071610429447853" data-width="1" data-height="0.023882975460122698" data-start-edge="right" data-speed="43" data-source-interval="854" data-pixel-size="5" data-color-fg="#FF8000" data-color-bg="#FFFFFF" data-source-type="noise" style="left: 0px; top: 200.269px; width: 652px; height: 15.5717px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.3310444785276074" data-width="1" data-height="0.008378803680981595" data-start-edge="right" data-speed="74" data-source-interval="559" data-pixel-size="4" data-color-fg="#800080" data-color-bg="#000000" data-source-type="noise" style="left: 0px; top: 215.841px; width: 652px; height: 5.46298px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.3394233128834356" data-width="1" data-height="0.03734831288343558" data-start-edge="left" data-speed="92" data-source-interval="1823" data-pixel-size="1" data-color-fg="#FF8000" data-color-bg="#FFFFFF" data-source-type="noise" style="left: 0px; top: 221.304px; width: 652px; height: 24.3511px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.37677147239263803" data-width="1" data-height="0.011757714723926381" data-start-edge="top" data-speed="91" data-source-interval="1741" data-pixel-size="2" data-color-fg="#FF8000" data-color-bg="#FFFFFF" data-source-type="noise" style="left: 0px; top: 245.655px; width: 652px; height: 7.66603px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.3885291411042945" data-width="1" data-height="0.03333665644171779" data-start-edge="bottom" data-speed="32" data-source-interval="1158" data-pixel-size="4" data-color-fg="#800080" data-color-bg="#000000" data-source-type="noise" style="left: 0px; top: 253.321px; width: 652px; height: 21.7355px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.4218650306748466" data-width="1" data-height="0.0070917944785276075" data-start-edge="top" data-speed="97" data-source-interval="594" data-pixel-size="3" data-color-fg="#800080" data-color-bg="#000000" data-source-type="noise" style="left: 0px; top: 275.056px; width: 652px; height: 4.62385px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.42895705521472394" data-width="1" data-height="0.005964969325153374" data-start-edge="bottom" data-speed="50" data-source-interval="1472" data-pixel-size="5" data-color-fg="#800080" data-color-bg="#000000" data-source-type="noise" style="left: 0px; top: 279.68px; width: 652px; height: 3.88916px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.4349217791411043" data-width="1" data-height="0.026651073619631902" data-start-edge="left" data-speed="99" data-source-interval="1274" data-pixel-size="3" data-color-fg="#800080" data-color-bg="#000000" data-source-type="noise" style="left: 0px; top: 283.569px; width: 652px; height: 17.3765px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.46157361963190185" data-width="1" data-height="0.007253558282208589" data-start-edge="left" data-speed="60" data-source-interval="1057" data-pixel-size="1" data-color-fg="#800080" data-color-bg="#000000" data-source-type="noise" style="left: 0px; top: 300.946px; width: 652px; height: 4.72932px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.46882668711656444" data-width="1" data-height="0.03476549079754601" data-start-edge="top" data-speed="89" data-source-interval="1618" data-pixel-size="4" data-color-fg="#FF8000" data-color-bg="#FFFFFF" data-source-type="noise" style="left: 0px; top: 305.675px; width: 652px; height: 22.6671px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.5035920245398773" data-width="1" data-height="0.006140398773006135" data-start-edge="top" data-speed="59" data-source-interval="1307" data-pixel-size="3" data-color-fg="#800080" data-color-bg="#000000" data-source-type="noise" style="left: 0px; top: 328.342px; width: 652px; height: 4.00354px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.5097331288343558" data-width="1" data-height="0.0219079754601227" data-start-edge="bottom" data-speed="48" data-source-interval="810" data-pixel-size="5" data-color-fg="#800080" data-color-bg="#000000" data-source-type="noise" style="left: 0px; top: 332.346px; width: 652px; height: 14.284px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.5316411042944785" data-width="1" data-height="0.0207069018404908" data-start-edge="left" data-speed="61" data-source-interval="1013" data-pixel-size="3" data-color-fg="#FF8000" data-color-bg="#FFFFFF" data-source-type="noise" style="left: 0px; top: 346.63px; width: 652px; height: 13.5009px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.5523481595092025" data-width="1" data-height="0.04458696319018405" data-start-edge="top" data-speed="64" data-source-interval="913" data-pixel-size="4" data-color-fg="#FF8000" data-color-bg="#FFFFFF" data-source-type="noise" style="left: 0px; top: 360.131px; width: 652px; height: 29.0707px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.5969340490797547" data-width="1" data-height="0.0061741411042944795" data-start-edge="bottom" data-speed="59" data-source-interval="1564" data-pixel-size="4" data-color-fg="#FF8000" data-color-bg="#FFFFFF" data-source-type="noise" style="left: 0px; top: 389.201px; width: 652px; height: 4.02554px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.6031088957055214" data-width="1" data-height="0.0313441717791411" data-start-edge="right" data-speed="40" data-source-interval="1511" data-pixel-size="2" data-color-fg="#800080" data-color-bg="#000000" data-source-type="noise" style="left: 0px; top: 393.227px; width: 652px; height: 20.4364px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.6344524539877301" data-width="1" data-height="0.011529049079754602" data-start-edge="left" data-speed="61" data-source-interval="1177" data-pixel-size="6" data-color-fg="#800080" data-color-bg="#000000" data-source-type="noise" style="left: 0px; top: 413.663px; width: 652px; height: 7.51694px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.6459815950920246" data-width="1" data-height="0.008259831288343558" data-start-edge="bottom" data-speed="49" data-source-interval="1686" data-pixel-size="1" data-color-fg="#800080" data-color-bg="#000000" data-source-type="noise" style="left: 0px; top: 421.18px; width: 652px; height: 5.38541px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.6542423312883435" data-width="1" data-height="0.011540230061349693" data-start-edge="bottom" data-speed="56" data-source-interval="742" data-pixel-size="1" data-color-fg="#800080" data-color-bg="#000000" data-source-type="noise" style="left: 0px; top: 426.566px; width: 652px; height: 7.52423px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.665782208588957" data-width="1" data-height="0.030010889570552146" data-start-edge="bottom" data-speed="85" data-source-interval="880" data-pixel-size="4" data-color-fg="#800080" data-color-bg="#000000" data-source-type="noise" style="left: 0px; top: 434.09px; width: 652px; height: 19.5671px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.6957929447852761" data-width="1" data-height="0.0389521472392638" data-start-edge="top" data-speed="25" data-source-interval="1576" data-pixel-size="6" data-color-fg="#800080" data-color-bg="#000000" data-source-type="noise" style="left: 0px; top: 453.657px; width: 652px; height: 25.3968px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.734745398773006" data-width="1" data-height="0.030821932515337425" data-start-edge="left" data-speed="78" data-source-interval="646" data-pixel-size="2" data-color-fg="#FF8000" data-color-bg="#FFFFFF" data-source-type="noise" style="left: 0px; top: 479.054px; width: 652px; height: 20.0959px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.7655674846625766" data-width="1" data-height="0.032648773006134967" data-start-edge="top" data-speed="55" data-source-interval="1390" data-pixel-size="1" data-color-fg="#FF8000" data-color-bg="#FFFFFF" data-source-type="noise" style="left: 0px; top: 499.15px; width: 652px; height: 21.287px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.7982162576687116" data-width="1" data-height="0.010342914110429447" data-start-edge="bottom" data-speed="62" data-source-interval="801" data-pixel-size="4" data-color-fg="#800080" data-color-bg="#000000" data-source-type="noise" style="left: 0px; top: 520.437px; width: 652px; height: 6.74358px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.8085582822085888" data-width="1" data-height="0.03908865030674847" data-start-edge="top" data-speed="63" data-source-interval="1761" data-pixel-size="4" data-color-fg="#FF8000" data-color-bg="#FFFFFF" data-source-type="noise" style="left: 0px; top: 527.18px; width: 652px; height: 25.4858px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.8476472392638038" data-width="1" data-height="0.00481388036809816" data-start-edge="top" data-speed="52" data-source-interval="985" data-pixel-size="6" data-color-fg="#FF8000" data-color-bg="#FFFFFF" data-source-type="noise" style="left: 0px; top: 552.666px; width: 652px; height: 3.13865px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.8524616564417177" data-width="1" data-height="0.023868711656441718" data-start-edge="right" data-speed="51" data-source-interval="718" data-pixel-size="2" data-color-fg="#800080" data-color-bg="#000000" data-source-type="noise" style="left: 0px; top: 555.805px; width: 652px; height: 15.5624px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.876329754601227" data-width="1" data-height="0.018872852760736195" data-start-edge="right" data-speed="95" data-source-interval="1297" data-pixel-size="6" data-color-fg="#FF8000" data-color-bg="#FFFFFF" data-source-type="noise" style="left: 0px; top: 571.367px; width: 652px; height: 12.3051px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.8952024539877301" data-width="1" data-height="0.03255828220858896" data-start-edge="bottom" data-speed="92" data-source-interval="1489" data-pixel-size="2" data-color-fg="#800080" data-color-bg="#000000" data-source-type="noise" style="left: 0px; top: 583.672px; width: 652px; height: 21.228px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.9277607361963189" data-width="1" data-height="0.03214739263803681" data-start-edge="left" data-speed="62" data-source-interval="583" data-pixel-size="3" data-color-fg="#800080" data-color-bg="#000000" data-source-type="noise" style="left: 0px; top: 604.9px; width: 652px; height: 20.9601px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.9599079754601227" data-width="1" data-height="0.03284294478527607" data-start-edge="top" data-speed="95" data-source-interval="1275" data-pixel-size="4" data-color-fg="#FF8000" data-color-bg="#FFFFFF" data-source-type="noise" style="left: 0px; top: 625.86px; width: 652px; height: 21.4136px;"><canvas></canvas></div><div class="smear-container" data-x="0" data-y="0.9927515337423313" data-width="1" data-height="0.0072486349693251535" data-start-edge="right" data-speed="45" data-source-interval="613" data-pixel-size="3" data-color-fg="#800080" data-color-bg="#000000" data-source-type="noise" style="left: 0px; top: 647.274px; width: 652px; height: 4.72611px;"><canvas></canvas></div></div><script> class SmearCanvas { constructor(c) { this.container = c; this.canvas = c.querySelector("canvas") || document.createElement("canvas"); if (!c.querySelector("canvas")) c.appendChild(this.canvas); this.ctx = this.canvas.getContext("2d"); this.ctx.imageSmoothingEnabled = false; this.imageData = null; this.lastTime = 0; this.animationId = null; this.speed = parseInt(c.dataset.speed) || 50; this.pixelSize = parseInt(c.dataset.pixelSize) || 2; this.sourceInterval = parseInt(c.dataset.sourceInterval) || 1000; this.colorFg = c.dataset.colorFg || "#FFFFFF"; this.colorBg = c.dataset.colorBg || "#000000"; this.sourceType = c.dataset.sourceType || "noise"; this.startEdge = c.dataset.startEdge || "top"; this.fgRGB = this.hexToRGB(this.colorFg); this.bgRGB = this.hexToRGB(this.colorBg); this.moveSpeed = (1000 / 60) / this.speed; this.subPixelX = 0; this.subPixelY = 0; this.leadX = 0; this.leadY = 0; this.initDirection(); this.lastDirectionChange = 0; this.nextDirectionInterval = this.randomInterval(); this.sourceParams = this.generateSourceParams(); this.lastSourceTime = 0; this.resize(); this.initCanvas(); this.generateSourceEdge(); this.initLeadPosition(); this.startAnimation(); this.resizeObserver = new ResizeObserver(() => this.resize()); this.resizeObserver.observe(this.container); } generateSourceParams() { return { steps: 3 + Math.floor(Math.random() * 6), stripeWidth: 2 + Math.floor(Math.random() * 8), checkSize: 1 + Math.floor(Math.random() * 4), phase: 0, dashLength: 3 + Math.floor(Math.random() * 10), gapLength: 2 + Math.floor(Math.random() * 6), density: 0.05 + Math.random() * 0.25, frequency: 1 + Math.random() * 4, sinePhase: Math.random() * Math.PI * 2, seed1: Math.random() * 100, seed2: Math.random() * 100, seed3: Math.random() * 100, counter: Math.floor(Math.random() * 65536), caRule: Math.random() > 0.5 ? 30 : 110 }; } initDirection() { switch (this.startEdge) { case "top": this.dx = 0; this.dy = 1; break; case "bottom": this.dx = 0; this.dy = -1; break; case "left": this.dx = 1; this.dy = 0; break; case "right": this.dx = -1; this.dy = 0; break; default: this.dx = 0; this.dy = 1; } } initLeadPosition() { switch (this.startEdge) { case "top": this.leadX = Math.floor(this.internalWidth / 2); this.leadY = 1; break; case "bottom": this.leadX = Math.floor(this.internalWidth / 2); this.leadY = this.internalHeight - 2; break; case "left": this.leadX = 1; this.leadY = Math.floor(this.internalHeight / 2); break; case "right": this.leadX = this.internalWidth - 2; this.leadY = Math.floor(this.internalHeight / 2); break; } } resize() { var rect = this.container.getBoundingClientRect(); if (rect.width === 0 || rect.height === 0) return; this.internalWidth = Math.ceil(rect.width / this.pixelSize); this.internalHeight = Math.ceil(rect.height / this.pixelSize); var oldImageData = this.imageData; var oldWidth = this.canvas.width; var oldHeight = this.canvas.height; this.canvas.width = this.internalWidth; this.canvas.height = this.internalHeight; this.imageData = this.ctx.createImageData(this.internalWidth, this.internalHeight); if (oldImageData && oldWidth > 0 && oldHeight > 0) { var minW = Math.min(oldWidth, this.internalWidth); var minH = Math.min(oldHeight, this.internalHeight); for (var y = 0; y < minH; y++) { for (var x = 0; x < minW; x++) { var oi = (y * oldWidth + x) * 4; var ni = (y * this.internalWidth + x) * 4; this.imageData.data[ni] = oldImageData.data[oi]; this.imageData.data[ni + 1] = oldImageData.data[oi + 1]; this.imageData.data[ni + 2] = oldImageData.data[oi + 2]; this.imageData.data[ni + 3] = oldImageData.data[oi + 3]; } } } } hexToRGB(hex) { var r = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); return r ? { r: parseInt(r[1], 16), g: parseInt(r[2], 16), b: parseInt(r[3], 16) } : { r: 255, g: 255, b: 255 }; } lerpColor(t) { return { r: Math.round(this.bgRGB.r + (this.fgRGB.r - this.bgRGB.r) * t), g: Math.round(this.bgRGB.g + (this.fgRGB.g - this.bgRGB.g) * t), b: Math.round(this.bgRGB.b + (this.fgRGB.b - this.bgRGB.b) * t) }; } getSourceValue(pos, length) { var t = pos / length; switch (this.sourceType) { case "noise": return Math.random() > 0.5 ? this.fgRGB : this.bgRGB; case "linear-gradient": return this.lerpColor(t); case "stepped-gradient": var steps = this.sourceParams.steps || 5; return this.lerpColor(Math.floor(t * steps) / (steps - 1)); case "random-gradient": if (!this.gradientCache || this.gradientCache.length !== length) this.generateRandomGradient(length); return this.lerpColor(this.gradientCache[pos]); case "stripes": return (Math.floor(pos / (this.sourceParams.stripeWidth || 4)) % 2 === 0) ? this.fgRGB : this.bgRGB; case "checkerboard": return ((Math.floor(pos / (this.sourceParams.checkSize || 2)) + (this.sourceParams.phase || 0)) % 2 === 0) ? this.fgRGB : this.bgRGB; case "dashes": var cycle = (this.sourceParams.dashLength || 6) + (this.sourceParams.gapLength || 3); return (pos % cycle < (this.sourceParams.dashLength || 6)) ? this.fgRGB : this.bgRGB; case "dots": return Math.random() < (this.sourceParams.density || 0.15) ? this.fgRGB : this.bgRGB; case "sine": var sv = (Math.sin((t * (this.sourceParams.frequency || 2) * Math.PI * 2) + (this.sourceParams.sinePhase || 0)) + 1) / 2; return this.lerpColor(sv); case "perlin": var p1 = Math.sin(t * 3.7 + this.sourceParams.seed1) * 0.5; var p2 = Math.sin(t * 7.3 + this.sourceParams.seed2) * 0.25; var p3 = Math.sin(t * 13.1 + this.sourceParams.seed3) * 0.125; return this.lerpColor(Math.max(0, Math.min(1, (p1 + p2 + p3 + 0.875) / 1.75))); case "binary-counter": return ((this.sourceParams.counter >> (pos % 16)) & 1) ? this.fgRGB : this.bgRGB; case "cellular-automata": if (!this.caState || this.caState.length !== length) this.initCellularAutomata(length); return this.caState[pos] ? this.fgRGB : this.bgRGB; default: return Math.random() > 0.5 ? this.fgRGB : this.bgRGB; } } generateRandomGradient(length) { var np = 3 + Math.floor(Math.random() * 4); var cp = [0]; for (var i = 1; i < np - 1; i++) cp.push(Math.random()); cp.push(1); cp.sort((a, b) => a - b); var cv = cp.map(() => Math.random()); this.gradientCache = []; for (var i = 0; i < length; i++) { var t = i / length; var si = 0; for (var j = 0; j < cp.length - 1; j++) { if (t >= cp[j] && t <= cp[j + 1]) { si = j; break; } } var st = (t - cp[si]) / (cp[si + 1] - cp[si]); this.gradientCache.push(cv[si] + (cv[si + 1] - cv[si]) * st); } } initCellularAutomata(length) { this.caState = []; for (var i = 0; i < length; i++) this.caState.push(Math.random() > 0.5); } evolveCellularAutomata() { if (!this.caState) return; var rule = this.sourceParams.caRule || 30; var os = [...this.caState]; var len = this.caState.length; for (var i = 0; i < len; i++) { var p = (os[(i - 1 + len) % len] ? 4 : 0) + (os[i] ? 2 : 0) + (os[(i + 1) % len] ? 1 : 0); this.caState[i] = ((rule >> p) & 1) === 1; } } updateSourceParams() { switch (this.sourceType) { case "checkerboard": this.sourceParams.phase = (this.sourceParams.phase + 1) % 2; break; case "sine": this.sourceParams.sinePhase += 0.5; break; case "binary-counter": this.sourceParams.counter++; break; case "cellular-automata": this.evolveCellularAutomata(); break; case "random-gradient": this.gradientCache = null; break; case "perlin": this.sourceParams.seed1 += 0.3; this.sourceParams.seed2 += 0.2; this.sourceParams.seed3 += 0.1; break; } } randomInterval() { return 100 + Math.random() * 900; } changeDirection() { var dirs = [[0, 1], [1, 1], [1, 0], [1, -1], [0, -1], [-1, -1], [-1, 0], [-1, 1]]; var idx = dirs.findIndex(d => d[0] === this.dx && d[1] === this.dy); if (idx === -1) idx = 0; idx = Math.random() > 0.5 ? (idx + 1) % 8 : (idx + 7) % 8; this.dx = dirs[idx][0]; this.dy = dirs[idx][1]; } initCanvas() { if (!this.imageData) return; var data = this.imageData.data; var w = this.internalWidth, h = this.internalHeight; var isH = (this.startEdge === "top" || this.startEdge === "bottom"); for (var y = 0; y < h; y++) { for (var x = 0; x < w; x++) { var idx = (y * w + x) * 4; var col = this.getSourceValue(isH ? x : y, isH ? w : h); data[idx] = col.r; data[idx + 1] = col.g; data[idx + 2] = col.b; data[idx + 3] = 255; } } this.ctx.putImageData(this.imageData, 0, 0); } generateSourceEdge() { if (!this.imageData) return; this.updateSourceParams(); var data = this.imageData.data; var w = this.internalWidth, h = this.internalHeight; var gen = (getIdx, len) => { for (var i = 0; i < len; i++) { var idx = getIdx(i); var c = this.getSourceValue(i, len); data[idx] = c.r; data[idx + 1] = c.g; data[idx + 2] = c.b; data[idx + 3] = 255; } }; switch (this.startEdge) { case "top": gen(x => x * 4, w); break; case "bottom": gen(x => ((h - 1) * w + x) * 4, w); break; case "left": gen(y => (y * w) * 4, h); break; case "right": gen(y => (y * w + (w - 1)) * 4, h); break; } } getSourceEdgeCoord(x, y) { switch (this.startEdge) { case "top": return y === 0; case "bottom": return y === this.internalHeight - 1; case "left": return x === 0; case "right": return x === this.internalWidth - 1; } return false; } smear() { if (!this.imageData) return; var data = this.imageData.data; var w = this.internalWidth, h = this.internalHeight; this.subPixelX += this.dx * this.moveSpeed; this.subPixelY += this.dy * this.moveSpeed; var moveX = Math.trunc(this.subPixelX), moveY = Math.trunc(this.subPixelY); if (moveX === 0 && moveY === 0) return; this.subPixelX -= moveX; this.subPixelY -= moveY; this.leadX += moveX; this.leadY += moveY; if (this.leadX <= 0 || this.leadX >= w - 1) { this.dx = -this.dx; this.leadX = Math.max(0, Math.min(w - 1, this.leadX)); } if (this.leadY <= 0 || this.leadY >= h - 1) { this.dy = -this.dy; this.leadY = Math.max(0, Math.min(h - 1, this.leadY)); } var oldData = new Uint8ClampedArray(data); for (var y = 0; y < h; y++) { for (var x = 0; x < w; x++) { if (this.getSourceEdgeCoord(x, y)) continue; var srcX = Math.max(0, Math.min(w - 1, x - moveX)); var srcY = Math.max(0, Math.min(h - 1, y - moveY)); var dstIdx = (y * w + x) * 4, srcIdx = (srcY * w + srcX) * 4; data[dstIdx] = oldData[srcIdx]; data[dstIdx + 1] = oldData[srcIdx + 1]; data[dstIdx + 2] = oldData[srcIdx + 2]; data[dstIdx + 3] = oldData[srcIdx + 3]; } } } startAnimation() { var fi = 1000 / 60; var animate = (ts) => { if (!this.lastTime) this.lastTime = ts; if (!this.lastSourceTime) this.lastSourceTime = ts; if (!this.lastDirectionChange) this.lastDirectionChange = ts; if (ts - this.lastDirectionChange >= this.nextDirectionInterval) { this.changeDirection(); this.lastDirectionChange = ts; this.nextDirectionInterval = this.randomInterval(); } if (ts - this.lastSourceTime >= this.sourceInterval) { this.generateSourceEdge(); this.lastSourceTime = ts; } if (ts - this.lastTime >= fi) { this.smear(); if (this.imageData) this.ctx.putImageData(this.imageData, 0, 0); this.lastTime = ts; } this.animationId = requestAnimationFrame(animate); }; this.animationId = requestAnimationFrame(animate); } } function layoutSmears() { var vw = window.innerWidth, vh = window.innerHeight; document.querySelectorAll(".smear-container").forEach(function(div) { var x = parseFloat(div.dataset.x || 0); var y = parseFloat(div.dataset.y || 0); var w = parseFloat(div.dataset.width || 0); var h = parseFloat(div.dataset.height || 0); div.style.left = (x * vw) + "px"; div.style.top = (y * vh) + "px"; div.style.width = (w * vw) + "px"; div.style.height = (h * vh) + "px"; }); } function initSmears() { document.querySelectorAll(".smear-container").forEach(function(c) { if (!c._smearInstance) c._smearInstance = new SmearCanvas(c); }); } window.addEventListener("load", function() { layoutSmears(); initSmears(); }); window.addEventListener("resize", layoutSmears); layoutSmears(); initSmears(); </script></body></html>