Public
Edited
Nov 10, 2023
1 fork
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
<div id='statsMonitorDiv'>${statsMonitor.dom}</div>
<div id='canvasDiv'>
${canvasStuff.canvas}
</div>
Insert cell
canvasStuff = {
refreshBtn;

const canvas = DOM.canvas(width, height),
ctx = canvas.getContext("2d"),
imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);

return { canvas, ctx, imageData };
}
Insert cell
gradientSteps = (initX = 0.6, initY = 0.4, t = 0.5) => {
const { ctx } = canvasStuff,
trace = [],
scaleX = d3.scaleLinear().domain([0, 1]).range([0, width]),
scaleY = d3.scaleLinear().domain([0, 1]).range([0, height]);

{
var x = initX, //d3.randomUniform()(),
y = initY, //d3.randomUniform()();
dx,
dy,
n = 100;

trace.push(Object.assign({}, { r: 0, i: 0, x, y }));

for (let i = 1; i < n + 1; ++i) {
dx = dfdx(x, y, t) * unitX;
dy = dfdy(x, y, t) * unitX;
x += dx;
y += dy;
trace.push(Object.assign({}, { r: i / n, i, x, y }));
}

// console.log(trace);
}

// const drawPnt = ({ r, i, x, y }) => {
// ctx.beginPath();
// ctx.rect(scaleX(x), scaleY(y), 3, 3);
// ctx.fillStyle = d3.interpolateWarm(r); //"white";
// ctx.fill();
// };
// trace.map((d) => drawPnt(d));

for (let i = 1; i < trace.length; ++i) {
const { x: x1, y: y1, r } = trace[i - 1],
{ x: x2, y: y2 } = trace[i];

ctx.beginPath();
ctx.moveTo(scaleX(x1), scaleY(y1));
ctx.lineTo(scaleX(x2), scaleY(y2));
ctx.strokeStyle = d3.interpolateWarm(r);
ctx.lineWidth = 5;
ctx.stroke();

if (i === 1 || i === trace.length - 1) {
ctx.beginPath();
ctx.rect(scaleX(x1) - 10, scaleY(y1) - 10, 20, 20);
ctx.strokeStyle = "white";
ctx.lineWidth = 1;
ctx.stroke();
}
}
}
Insert cell
d3.interpolateWarm(0)
Insert cell
{
refreshBtn;

const { canvas, ctx, imageData, tStep } = canvasStuff,
{ width, height } = canvas,
{ data } = imageData;

var x,
y,
v,
r,
g = 10,
b;

function drawPlasma(secs = 0.5) {
const t = (secs / 5) * timeScaler;

for (let i = 0; i < width; i++) {
for (let j = 0; j < height; j++) {
x = i / width;
y = j / height;

v = getPixel(x, y, t); // * 0.5 + 0.5;

if (v > 0) {
r = v * 200;
b = 0;
} else {
r = 0;
b = -v * 200;
}

data[(i + j * width) * 4 + 0] = r;
data[(i + j * width) * 4 + 1] = g;
data[(i + j * width) * 4 + 2] = b;
data[(i + j * width) * 4 + 3] = 255;
}
}

ctx.putImageData(imageData, 0, 0);

gradientSteps(0.4, 0.6, t);
gradientSteps(0.5, 0.6, t);
gradientSteps(0.4, 0.5, t);
gradientSteps(0.5, 0.5, t);

statsMonitor.update();

return t;
}

var secs = performance.now() / 1000;

drawPlasma(secs);

while (toggle) {
secs = performance.now() / 1000;
yield drawPlasma(secs);
// yield secs;
}
}
Insert cell
dfdx = (x, y, t) => {
const dx = 1 / 100,
df = getPixel(x + dx, y, t) - getPixel(x, y, t);

return df / dx;
}
Insert cell
dfdy = (x, y, t) => {
const dy = 1 / 100,
df = getPixel(x, y + dy, t) - getPixel(x, y, t);

return df / dy;
}
Insert cell
unitX = 1 / width
Insert cell
unitY = 1 / height
Insert cell
getPixel = (x, y, t) => {
return noiseGen.noise3D(x * 2, y * 2, t);
}
Insert cell
noiseGen = {
const noiseGen = new simplexNoise(d3.randomUniform()());
return noiseGen;
}
Insert cell
width = 600
Insert cell
height = 400
Insert cell
statsMonitor = {
const stats = new Stats(),
{ dom } = stats;
dom.style.position = "relative";

return stats;
}
Insert cell
Stats = await require("https://cdn.jsdelivr.net/npm/stats-js@1.0.1/build/stats.min.js")
Insert cell
simplexNoise = require("simplex-noise@2.4.0")
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more