Skip to content

Instantly share code, notes, and snippets.

@asong56
Created April 1, 2026 00:27
Show Gist options
  • Select an option

  • Save asong56/01b30191554a3aed290f12256296c1e6 to your computer and use it in GitHub Desktop.

Select an option

Save asong56/01b30191554a3aed290f12256296c1e6 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Optimized Vector Field</title>
<style>
body { margin: 0; overflow: hidden; background: #f4f5f7; touch-action: none; }
canvas { display: block; width: 100vw; height: 100vh; }
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d', { alpha: false });
let width, height;
let shards;
let mouse = { x: -1000, y: -1000, pressed: false };
const config = {
spacing: 40,
halfLen: 5,
vibration: 3.0
};
function initGrid() {
const dpr = window.devicePixelRatio || 1;
width = window.innerWidth;
height = window.innerHeight;
canvas.width = width * dpr;
canvas.height = height * dpr;
ctx.scale(dpr, dpr);
const cols = Math.floor(width / config.spacing);
const rows = Math.floor(height / config.spacing);
shards = new Float32Array(cols * rows * 3);
let i = 0;
for(let x = config.spacing; x < width; x += config.spacing) {
for(let y = config.spacing; y < height; y += config.spacing) {
shards[i++] = x; // anchorX
shards[i++] = y; // anchorY
shards[i++] = 0; // angle
}
}
}
function draw() {
ctx.fillStyle = '#f4f5f7';
ctx.fillRect(0, 0, width, height);
ctx.beginPath();
ctx.strokeStyle = 'rgba(60, 80, 110, 0.6)';
ctx.lineWidth = 0.7;
const { x: mx, y: my, pressed } = mouse;
const { halfLen, vibration } = config;
for(let i = 0; i < shards.length; i += 3) {
const ax = shards[i];
const ay = shards[i+1];
let angle = shards[i+2];
const dx = mx - ax;
const dy = my - ay;
angle += (Math.atan2(dy, dx) - angle) * 0.1;
shards[i+2] = angle;
let x = ax;
let y = ay;
if (pressed) {
x += (Math.random() - 0.5) * vibration;
y += (Math.random() - 0.5) * vibration;
const dist = Math.hypot(dx, dy);
if (dist > 0) {
x += (dx / dist) * 10;
y += (dy / dist) * 10;
}
}
const cos = Math.cos(angle) * halfLen;
const sin = Math.sin(angle) * halfLen;
ctx.moveTo(x - cos, y - sin);
ctx.lineTo(x + cos, y + sin);
}
ctx.stroke();
requestAnimationFrame(draw);
}
window.addEventListener('pointermove', e => { mouse.x = e.clientX; mouse.y = e.clientY; });
window.addEventListener('pointerdown', () => mouse.pressed = true);
window.addEventListener('pointerup', () => mouse.pressed = false);
window.addEventListener('resize', initGrid);
initGrid();
draw();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment