// Inspired by https://youtu.be/M_SUcX66SDA Low Byte Productions Flow Fields video import { vScale, vAdd, vAngle } from "./util.js"; //const vAngle = (a) => [Math.cos(a), Math.sin(a)]; const canvas = document.getElementById("main"); const ctx = canvas.getContext("2d"); const width = 800; const height = 800; // A 10x10 grid, transformed onto the canvas const n = 25; const fieldSize = width/n; canvas.setAttribute("width", width); canvas.setAttribute("height", height); const fill = (ctx, r = 0, g = 0, b = 0, a = 255) => { ctx.fillStyle = `rgba(${r}, ${g}, ${b}, ${a})`; } const stroke = (ctx, r = 0, g = 0, b = 0, a = 255) => { ctx.strokeStyle = `rgba(${r}, ${g}, ${b}, ${a})`; }; const line = (ctx, v, v2) => { ctx.beginPath(); ctx.moveTo(...v); ctx.lineTo(...v2); ctx.stroke(); ctx.closePath(); } const ellipse = (ctx, v, rx, ry = rx, oa = 0, sa = 0, ea = Math.PI * 2) => { ctx.beginPath(); ctx.ellipse(...v, rx, ry, oa, sa, ea, false); ctx.stroke(); ctx.fill(); ctx.closePath(); } const background = (ctx, r = 0, g = 0, b = 0, a = 255) => { fill(ctx, r, g, b, a); ctx.fillRect(0, 0, width, height); } fill(ctx, 0,0,0,0); stroke(ctx, 255,255,255,1); background(ctx, 0, 0, 255, width, height); const vRandom = () => vAngle(Math.random() * Math.PI * 2); /* for (let y = 0; y < n; y++) { for (let x = 0; x < n; x++) { const sv = vAdd([fieldSize/2, fieldSize/2], vScale(fieldSize, [x, y])); ellipse(ctx, sv, fieldSize/2); } } */ let prevTimestamp; const draw = (timestamp) => { if (prevTimestamp === undefined) { prevTimestamp = timestamp; } const elapsed = timestamp - prevTimestamp; if (elapsed > 500) { prevTimestamp = timestamp; const field = Array.from({length: n}, () => Array.from({length: n}, () => { return vRandom(); })); fill(ctx, 0,0,0,0); stroke(ctx, 255,255,255,1); background(ctx, 0, 0, 255, width, height); field.forEach((row, y) => row.forEach((fv, x) => { const sv = vAdd([fieldSize/2, fieldSize/2], vScale(fieldSize, [x, y])); const upper = vAdd(sv, vScale(fieldSize/2, fv)); const lower = vAdd(sv, vScale(-fieldSize/2, fv)); line(ctx, upper, lower); fill(ctx, 255,255,255,1); ellipse(ctx, upper, 2); })); } window.requestAnimationFrame(draw); }; draw();