Skip to content

Instantly share code, notes, and snippets.

@ronwnor
Created October 28, 2023 08:20
Show Gist options
  • Select an option

  • Save ronwnor/ffcf24af1318ffeb0589cfbb92976438 to your computer and use it in GitHub Desktop.

Select an option

Save ronwnor/ffcf24af1318ffeb0589cfbb92976438 to your computer and use it in GitHub Desktop.
bezierCurvature
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const tau = 2 * Math.PI;
const DEGREE = 9, CIRCLES = 3000;
document.body.append(canvas);
(onresize = () => {
canvas.width = innerWidth;
canvas.height = innerHeight;
ctx.globalCompositeOperation = 'lighter';
ctx.lineWidth = .05;
})();
document.body.style = `
margin: 0;
padding: 0;
overflow: hidden;
`;
canvas.style = `
background: black;
width: 100%;
height: 100%;
`;
let rx = [...Array(DEGREE)],
ry = [...Array(DEGREE)];
function nCr(n,r){
let sum = 1;
for(let i=1; i<=r; i++){
sum *= (n-r)/i + 1;
}
return sum|0;
}
function len(z){
return Math.hypot(z.x, z.y);
}
function Bez(order){
function bez(t){
let x = 0,
y = 0,
len = rx.length - 1 - order;
for(let i=0, tmp; i<=len; i++){
tmp = nCr(len, i) * (1 - t)**(len - i) * t**i;
switch(order){
case 0:
x += rx[i] * tmp;
y += ry[i] * tmp;
break;
case 1:
x += (rx[i+1] - rx[i]) * tmp;
y += (ry[i+1] - ry[i]) * tmp;
break;
case 2:
x += (rx[i+2] - 2*rx[i+1] + rx[i]) * tmp;
y += (ry[i+2] - 2*ry[i+1] + ry[i]) * tmp;
break;
}
}
if(order){
x *= len + 1;
y *= len + 1;
} if (order == 2){
x *= len + 2;
y *= len + 2;
}
return {x, y};
}
return bez;
}
let f = Bez(0),
df = Bez(1),
ddf = Bez(2);
function circle(x, y, r) {
ctx.beginPath();
ctx.arc(x, y, r, 0, tau);
ctx.stroke();
}
ctx.globalCompositeOperation = 'lighter';
ctx.lineWidth = .02;
let count = -1/32, paused = false;
let rx0,ry0,
rx1 = rx.map(() => canvas.width * Math.random()),
ry1 = ry.map(() => canvas.width * Math.random());
let interval = setInterval(() => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if(!paused && !(count=(count+1/32)%1)){
rx0 = structuredClone(rx1);
ry0 = structuredClone(ry1);
rx1 = rx.map(() => canvas.width * Math.random());
ry1 = rx.map(() => canvas.height * Math.random());
}
let smooth = .5 + .5 * Math.tanh(8*count - 4) / Math.tanh(4);
for(let i in rx){
rx[i] = rx0[i] + (rx1[i] - rx0[i]) * smooth;
ry[i] = ry0[i] + (ry1[i] - ry0[i]) * smooth;
}
for(let t = 0; t <= 1; t += 1/CIRCLES){
let ft = f(t),
dft = df(t),
ddft = ddf(t);
let mag = len(dft),
curvature = mag * mag / (dft.x * ddft.y - dft.y * ddft.x);
let x = ft.x - dft.y * curvature,
y = ft.y + dft.x * curvature,
r = Math.abs(mag * curvature);
ctx.strokeStyle = `hsl(${200 + 100*t}, 60%, 50%)`;
circle(x, y, r)
}
}, 60);
onkeydown = e => { if(e.key == ' ') paused = !paused; }
@ronwnor
Copy link
Author

ronwnor commented Oct 28, 2023

run in about:blank or something
you can also use

fetch('https://gist.githubusercontent.com/ronwnor/ffcf24af1318ffeb0589cfbb92976438/raw/4433c8c361b3e1bd01a09c93b58ccf462dbfe743/curv.js')
    .then(e => e.text())
    .then(eval);

chrome_jD1KjLzSXA

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment