Move flow-fields code here
This commit is contained in:
parent
df621db3a2
commit
ef2f98ce53
15
README.md
15
README.md
@ -11,3 +11,18 @@ Or build with:
|
||||
```
|
||||
$ pnpm run build
|
||||
```
|
||||
|
||||
# Individual Projects
|
||||
|
||||
## Flow Fields
|
||||
|
||||
Inspired by https://youtu.be/M_SUcX66SDA Low Byte Productions Flow Fields video
|
||||
|
||||
Uses code from:
|
||||
* https://github.com/francisrstokes/vec-la-fp/tree/master
|
||||
* https://github.com/francisrstokes/microcan
|
||||
|
||||
|
||||
## Konva-ball
|
||||
|
||||
Experimenting with konva library
|
||||
|
13
src/flow-fields/index.html
Normal file
13
src/flow-fields/index.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Flow Fields</title>
|
||||
<script type="module" src="index.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<canvas id="main"></canvas>
|
||||
</body>
|
||||
</html>
|
104
src/flow-fields/index.js
Normal file
104
src/flow-fields/index.js
Normal file
@ -0,0 +1,104 @@
|
||||
// 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();
|
8
src/flow-fields/util.js
Normal file
8
src/flow-fields/util.js
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
const vScale = (scale, vec) => vec.map(n => n * scale);
|
||||
|
||||
const vAdd = (v0, v1) => [v0[0] + v1[0], v0[1] + v1[1]];
|
||||
|
||||
const vAngle = (a) => [Math.cos(a), Math.sin(a)];
|
||||
|
||||
export { vAdd, vScale, vAngle };
|
@ -8,6 +8,7 @@
|
||||
<h1>Spazer</h1>
|
||||
<ul>
|
||||
<li> <a href="./konva-ball/index.html">Konva-ball</a>
|
||||
<li> <a href="./flow-fields/index.html">Flow-fields</a>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
|
Loading…
Reference in New Issue
Block a user