{
let { n, speed, angleDrift, sizeDriftA, sizeDriftB } = config;
let {
background,
fill,
fillColor,
fillOpacity,
stroke,
strokeColor,
strokeOpacity,
lineWidth
} = colorConfig;
let { octaves, amplitude } = noiseConfig;
let size = 750;
let ctx = DOM.context2d(size, size);
let pos = [];
let d = size / n;
for (let i = 0; i <= n; i++) {
pos.push([]);
for (let j = 0; j <= n; j++) {
pos[i].push([i * d, j * d]);
}
}
let t = 0;
let noiseFunction = octave(perlin3, octaves);
let noise = (i, j, k) =>
noiseFunction((i / n) * amplitude, (j / n) * amplitude, k);
let refresh = () => {
t += 0.0001 * speed;
let pos = [];
for (let i = 0; i <= n; i++) {
pos.push([]);
for (let j = 0; j <= n; j++) {
let [x, y] = [i * d, j * d];
{
x += d * angleDrift * noise(i, j, -t);
y += d * angleDrift * noise(i, j, t);
}
pos[i].push([x, y]);
}
}
ctx.fillStyle = background;
ctx.fillRect(0, 0, size, size);
ctx.fillStyle =
fillColor + ("0" + (~~(fillOpacity * 255)).toString(16)).slice(-2);
ctx.strokeStyle =
strokeColor + ("0" + (~~(strokeOpacity * 255)).toString(16)).slice(-2);
ctx.lineJoin = "round";
ctx.lineWidth = lineWidth;
for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
let m = noise(i, j, t) * sizeDriftA + sizeDriftB;
let vtx = [pos[i][j], pos[i + 1][j], pos[i + 1][j + 1], pos[i][j + 1]];
let [cx, cy] = vtx.reduce(([x0, y0], [x1, y1]) => [x0 + x1, y0 + y1]);
cx /= 4;
cy /= 4;
ctx.beginPath();
vtx = vtx.map(([x, y]) => [x + (cx - x) * m, y + (cy - y) * m]);
ctx.moveTo(vtx[0][0], vtx[0][1]);
vtx.forEach(([x, y]) => ctx.lineTo(x, y));
ctx.closePath();
if (fill) ctx.fill();
if (stroke) ctx.stroke();
}
}
};
for (;;) {
await visibility();
refresh();
yield ctx.canvas;
}
}