Interactive visualization of the bitwise art formula (x & y) % (y - x) % 37, producing fractal interference patterns from Sierpinski-like structure modulated by diagonal banding.
---
format: typebulb/v1
name: Sierpinski Flow
---
**code.tsx**
```tsx
import React, { useState, useEffect, useRef, useCallback } from 'react';
import { createRoot } from 'react-dom/client';
const CONFIG = {
DEFAULT_SIZE: 512,
MIN_SIZE: 128,
MAX_SIZE: 1024,
DEFAULT_SPEED: 1,
MAX_SPEED: 10,
DEFAULT_MODULUS: 37,
MIN_MODULUS: 2,
MAX_MODULUS: 100,
} as const;
type PaletteMode = 'hue' | 'fire' | 'grayscale' | 'neon';
const PALETTES: Record<PaletteMode, (v: number, max: number) => [number, number, number]> = {
hue: (v, max) => {
const h = (v / max) * 360;
return hslToRgb(h, 0.9, 0.5);
},
fire: (v, max) => {
const t = v / max;
return [
Math.min(255, t * 3 * 255) | 0,
Math.min(255, Math.max(0, (t - 0.33) * 3 * 255)) | 0,
Math.min(255, Math.max(0, (t - 0.66) * 3 * 255)) | 0,
];
},
grayscale: (v, max) => {
const g = ((v / max) * 255) | 0;
return [g, g, g];
},
neon: (v, max) => {
const h = (v / max) * 360;
return hslToRgb(h, 1.0, 0.6);
},
};
function hslToRgb(h: number, s: number, l: number): [number, number, number] {
const c = (1 - Math.abs(2 * l - 1)) * s;
const x = c * (1 - Math.abs(((h / 60) % 2) - 1));
const m = l - c / 2;
let r = 0, g = 0, b = 0;
if (h < 60) { r = c; g = x; }
else if (h < 120) { r = x; g = c; }
else if (h < 180) { g = c; b = x; }
else if (h < 240) { g = x; b = c; }
else if (h < 300) { r = x; b = c; }
else { r = c; b = x; }
return [((r + m) * 255) | 0, ((g + m) * 255) | 0, ((b + m) * 255) | 0];
}
function computePixel(x: number, y: number, t: number, modulus: number): number {
const xt = (x + t) | 0;
const yt = (y + t) | 0;
const band = xt & yt;
const diff = yt - xt;
if (diff === 0) return 0;
return ((band % diff) % modulus + modulus) % modulus; // ensure non-negative
}
function renderFrame(
ctx: CanvasRenderingContext2D,
width: number,
height: number,
t: number,
modulus: number,
palette: PaletteMode,
zoom: number,
panX: number,
panY: number,
) {
const imageData = ctx.createImageData(width, height);
const data = imageData.data;
const colorFn = PALETTES[palette];
const invZoom = 1 / zoom;
for (let py = 0; py < height; py++) {
for (let px = 0; px < width; px++) {
const x = ((px - width / 2) * invZoom + panX) | 0;
const y = ((py - height / 2) * invZoom + panY) | 0;
const v = computePixel(x, y, t, modulus);
const [r, g, b] = colorFn(v, modulus);
const idx = (py * width + px) * 4;
data[idx] = r;
data[idx + 1] = g;
data[idx + 2] = b;
data[idx + 3] = 255;
}
}
ctx.putImageData(imageData, 0, 0);
}
function App() {
const canvasRef = useRef<HTMLCanvasElement>(null);
const animRef = useRef<number>(0);
const tRef = useRef(0);
const [isRunning, setIsRunning] = useState(true);
const [palette, setPalette] = useState<PaletteMode>('hue');
const [speed, setSpeed] = useState<number>(CONFIG.DEFAULT_SPEED);
const [modulus, setModulus] = useState<number>(CONFIG.DEFAULT_MODULUS);
const [zoom, setZoom] = useState<number>(1);
const [size, setSize] = useState<number>(CONFIG.DEFAULT_SIZE);
const [panX, setPanX] = useState<number>(256);
const [panY, setPanY] = useState<number>(256);
const [showInfo, setShowInfo] = useState(false);
const [currentT, setCurrentT] = useState<number>(0);
const stateRef = useRef({ palette, speed, modulus, zoom, panX, panY, size });
useEffect(() => {
stateRef.current = { palette, speed, modulus, zoom, panX, panY, size };
}, [palette, speed, modulus, zoom, panX, panY, size]);
const draw = useCallback(() => {
const canvas = canvasRef.current;
if (!canvas) return;
const ctx = canvas.getContext('2d');
if (!ctx) return;
const s = stateRef.current;
renderFrame(ctx, s.size, s.size, tRef.current, s.modulus, s.palette, s.zoom, s.panX, s.panY);
}, []);
const loop = useCallback(() => {
const s = stateRef.current;
tRef.current += s.speed;
setCurrentT(tRef.current);
draw();
animRef.current = requestAnimationFrame(loop);
}, [draw]);
useEffect(() => {
draw();
}, [palette, modulus, zoom, panX, panY, size]);
useEffect(() => {
if (isRunning) {
animRef.current = requestAnimationFrame(loop);
} else {
cancelAnimationFrame(animRef.current);
}
return () => cancelAnimationFrame(animRef.current);
}, [isRunning, loop]);
const step = () => {
tRef.current += 1;
setCurrentT(tRef.current);
draw();
};
const reset = () => {
setIsRunning(false);
tRef.current = 0;
setCurrentT(0);
setZoom(1);
setPanX(256);
setPanY(256);
setTimeout(draw, 0);
};
const handleWheel = (e: React.WheelEvent) => {
e.preventDefault();
const factor = e.deltaY < 0 ? 1.1 : 0.9;
setZoom(z => Math.max(0.1, Math.min(20, z * factor)));
};
const dragRef = useRef<{ startX: number; startY: number; startPanX: number; startPanY: number } | null>(null);
const handlePointerDown = (e: React.PointerEvent) => {
dragRef.current = { startX: e.clientX, startY: e.clientY, startPanX: panX, startPanY: panY };
(e.target as HTMLElement).setPointerCapture(e.pointerId);
};
const handlePointerMove = (e: React.PointerEvent) => {
if (!dragRef.current) return;
const dx = (e.clientX - dragRef.current.startX) / zoom;
const dy = (e.clientY - dragRef.current.startY) / zoom;
setPanX(dragRef.current.startPanX - dx);
setPanY(dragRef.current.startPanY - dy);
};
const handlePointerUp = () => {
dragRef.current = null;
};
return (
<div className="app">
<header className="header">
<h1>Sierpinski Flow</h1>
<button className="info-btn" onClick={() => setShowInfo(!showInfo)}>
{showInfo ? '▼' : '▶'} What is this?
</button>
{showInfo && (
<p className="info-text">
Each pixel at (x, y) is colored by <code>(x & y) % (y - x) % {modulus}</code>.
The bitwise AND produces Sierpinski-triangle-like fractal structure, while the
modular arithmetic by the diagonal distance <code>(y - x)</code> and then by the
selected number (default <code>{CONFIG.DEFAULT_MODULUS}</code>) creates banded
interference patterns. Press play to animate by shifting the coordinate origin
over time. Drag to pan, scroll to zoom.
</p>
)}
</header>
<div className="control-bar">
<div className="controls">
<button onClick={() => setIsRunning(!isRunning)} className="btn-icon">
{isRunning ? '⏸' : '▶'}
</button>
<button onClick={step} disabled={isRunning} className="btn-icon">⏭</button>
<button onClick={reset} className="btn-icon">↻</button>
<div className="info-stack">
<span className="info-text">t = <strong>{currentT}</strong></span>
<span className="info-text">zoom: <strong>{zoom.toFixed(1)}×</strong></span>
</div>
</div>
<div className="config-panel">
<div className="config-group">
<label>Speed</label>
<input type="range" min="1" max={CONFIG.MAX_SPEED} step="1" value={speed}
onChange={e => setSpeed(Number(e.target.value))} />
<span className="config-value">{speed}</span>
</div>
<div className="config-group">
<label>Number</label>
<input
type="range"
min={CONFIG.MIN_MODULUS}
max={CONFIG.MAX_MODULUS}
step="1"
value={modulus}
onChange={e => setModulus(Number(e.target.value))}
/>
<span className="config-value">{modulus}</span>
</div>
<div className="config-group">
<label>Resolution</label>
<input type="range" min={CONFIG.MIN_SIZE} max={CONFIG.MAX_SIZE} step="64" value={size}
onChange={e => setSize(Number(e.target.value))} />
<span className="config-value">{size}×{size}</span>
</div>
<div className="config-group">
<label>Palette</label>
<div className="palette-buttons">
{(Object.keys(PALETTES) as PaletteMode[]).map(p => (
<button key={p} className={`palette-btn ${p === palette ? 'active' : ''}`}
onClick={() => setPalette(p)}>
{p}
</button>
))}
</div>
</div>
</div>
</div>
<main className="content">
<div className="canvas-container"
onWheel={handleWheel}
onPointerDown={handlePointerDown}
onPointerMove={handlePointerMove}
onPointerUp={handlePointerUp}
>
<canvas
ref={canvasRef}
width={size}
height={size}
className="art-canvas"
/>
</div>
</main>
<footer className="footer-credit">
<span>Idea by Non-Euclidean Dreamer</span>
<span>@NonEuclideanDr1</span>
</footer>
</div>
);
}
const container = document.getElementById('root');
const root = createRoot(container!);
root.render(<App />);
```
**styles.css**
```css
:root {
--color-bg: #0a0a0a;
--color-surface: #1a1a1a;
--color-border: #333;
--color-text: #e0e0e0;
--color-text-secondary: #9e9e9e;
--color-primary: #7c4dff;
--color-primary-hover: #9e77ff;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: var(--color-bg);
color: var(--color-text);
line-height: 1.6;
}
.app {
min-height: 100vh;
display: flex;
flex-direction: column;
}
.header {
background: var(--color-surface);
border-bottom: 2px solid var(--color-border);
padding: 1rem 2rem;
text-align: center;
}
.header h1 {
font-size: 1.4rem;
font-weight: 600;
}
.header h1 code {
font-size: 1.1rem;
color: var(--color-primary);
}
.info-btn {
background: transparent;
border: none;
color: var(--color-text-secondary);
cursor: pointer;
font-size: 0.9rem;
font-weight: 600;
padding: 0.5rem 0;
margin-top: 0.5rem;
}
.info-btn:hover { color: var(--color-text); }
.info-text {
max-width: 700px;
margin: 0.75rem auto 0;
text-align: left;
font-size: 0.9rem;
color: var(--color-text-secondary);
line-height: 1.7;
}
.info-text code {
background: var(--color-border);
padding: 0.15rem 0.4rem;
border-radius: 3px;
font-size: 0.85rem;
}
.control-bar {
background: var(--color-surface);
border-bottom: 1px solid var(--color-border);
padding: 1rem 2rem;
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;
}
.controls {
display: flex;
gap: 0.5rem;
align-items: center;
flex-wrap: wrap;
justify-content: center;
}
.btn-icon {
padding: 0.75rem 1.25rem;
border: none;
border-radius: 6px;
font-size: 1.25rem;
cursor: pointer;
background: var(--color-primary);
color: white;
transition: all 0.2s;
min-width: 60px;
}
.btn-icon:hover {
background: var(--color-primary-hover);
transform: scale(1.05);
}
.btn-icon:disabled {
opacity: 0.4;
cursor: not-allowed;
transform: none;
}
.info-stack {
display: flex;
flex-direction: column;
gap: 0.1rem;
margin-left: 0.5rem;
}
.info-stack .info-text {
margin: 0;
font-size: 0.9rem;
white-space: nowrap;
}
.info-stack .info-text strong {
font-weight: 700;
color: var(--color-text);
}
.config-panel {
display: flex;
gap: 2rem;
flex-wrap: wrap;
justify-content: center;
}
.config-group {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.25rem;
min-width: 0;
}
.config-group label {
font-size: 0.85rem;
color: var(--color-text-secondary);
font-weight: 600;
}
.config-value {
color: var(--color-primary);
font-weight: 700;
font-size: 0.9rem;
}
.palette-buttons {
display: flex;
gap: 0.25rem;
}
.palette-btn {
padding: 0.3rem 0.6rem;
border: 1px solid var(--color-border);
border-radius: 4px;
background: transparent;
color: var(--color-text-secondary);
font-size: 0.8rem;
cursor: pointer;
transition: all 0.2s;
}
.palette-btn:hover {
border-color: var(--color-primary);
color: var(--color-text);
}
.palette-btn.active {
background: var(--color-primary);
color: white;
border-color: var(--color-primary);
}
.content {
flex: 1;
display: flex;
justify-content: center;
align-items: flex-start;
padding: 1.5rem 1.5rem 0.9rem;
}
.canvas-container {
cursor: grab;
touch-action: none;
border: 1px solid var(--color-border);
border-radius: 4px;
overflow: hidden;
line-height: 0;
}
.canvas-container:active {
cursor: grabbing;
}
.art-canvas {
display: block;
max-width: 90vw;
max-height: 75vh;
width: auto;
height: auto;
image-rendering: pixelated;
}
.footer-credit {
padding: 0.35rem 1rem 0.85rem;
display: flex;
flex-direction: column;
align-items: center;
gap: 0.1rem;
font-size: 0.8rem;
color: var(--color-text-secondary);
text-align: center;
}
input[type="range"] {
-webkit-appearance: none;
appearance: none;
background: var(--color-border);
outline: none;
border-radius: 4px;
height: 6px;
width: 120px;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 16px;
height: 16px;
background: var(--color-primary);
cursor: pointer;
border-radius: 50%;
}
input[type="range"]::-moz-range-thumb {
width: 16px;
height: 16px;
background: var(--color-primary);
cursor: pointer;
border-radius: 50%;
border: none;
}
@media (max-width: 640px) {
.header {
padding: 0.85rem 1rem;
}
.control-bar {
padding: 0.75rem 0.6rem;
gap: 0.75rem;
}
.controls {
gap: 0.35rem;
}
.btn-icon {
padding: 0.6rem 0.9rem;
min-width: 48px;
}
.info-stack {
margin-left: 0.25rem;
}
.config-panel {
width: 100%;
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
column-gap: 0.55rem;
row-gap: 0.7rem;
align-items: start;
}
.config-panel > .config-group {
min-width: 0;
}
.config-panel > .config-group:nth-child(-n + 3) {
align-items: stretch;
gap: 0.2rem;
}
.config-panel > .config-group:nth-child(-n + 3) label,
.config-panel > .config-group:nth-child(-n + 3) .config-value {
text-align: center;
}
.config-panel > .config-group:nth-child(-n + 3) label {
font-size: 0.75rem;
}
.config-panel > .config-group:nth-child(-n + 3) .config-value {
font-size: 0.8rem;
}
.config-panel > .config-group:nth-child(-n + 3) input[type="range"] {
width: 100%;
}
.config-panel > .config-group:nth-child(4) {
grid-column: 1 / -1;
align-items: center;
}
.palette-buttons {
flex-wrap: wrap;
justify-content: center;
}
}
```
**index.html**
```html
<div id="root"></div>
```
**config.json**
```json
{
"dependencies": {
"react": "^19.2.3",
"react-dom": "^19.2.3"
},
"description": "Interactive visualization of the bitwise art formula (x & y) % (y - x) % 37, producing fractal interference patterns from Sierpinski-like structure modulated by diagonal banding."
}
```