Public
Edited
Mar 6, 2024
2 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
const W = 540; // Canvas width and height, setting the size of the drawing area.
const N = 200; // The density of points. Determines how many points are drawn along each axis.
let x = 0, y = 0, t = 0; // Initializes x, y coordinates, and a time variable t for animation progression.

const ctx = DOM.context2d(W, W); // Creates a 2D drawing context for the specified width and height.
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, W, W); // Fills the canvas with black, serving as the background.

function F(i, j) {
const r = Math.PI * 2 / N;
let deviation = Math.random() * 2 - 1; // Random deviation
let deviationFactor = deviationValue; // Adjust the magnitude of the deviation
let u = Math.sin(i + y) + Math.sin(r * i + x + t) + deviation * deviationFactor * Math.random();
let v = Math.cos(i + y) + Math.cos(r * i + x + t) + deviation * deviationFactor * Math.random();
x = u; // Update global x
y = v; // Update global y
// Calculate distance from the center to the point
const distance = Math.sqrt(Math.pow(u * N / center, 2) + Math.pow(v * N / center, 2));
// To change the spread of the effect modifying the scaling factor (N / x) in the distance calculation can change how quickly the effect of fading or color change occurs as you move away from the center.
const maxDistance = Math.sqrt(Math.pow(W / fading, 2) + Math.pow(W / fading, 2));
// For a different distribution of points: Adjusting the calculation of u and v or how they are scaled (N / x factor) can alter the distribution pattern of points on the canvas, affecting the overall visual effect.
// Normalize distance and use it to adjust opacity or color
const normalizedDistance = distance / maxDistance;
const opacity = normalizedDistance; // Use this value to adjust opacity (0 at center to 1 at edges)
// Adjust fill style based on distance; closer to center means closer to black or more faded
ctx.fillStyle = `hsla(${(i % 360)}, 100%, 50%, ${opacity})`;
ctx.beginPath();
ctx.arc(u * N / 2 + W / 2, v * N / 2 + W / 2, 0.2, 0, Math.PI * 2);
ctx.fill();
}


function update() {
ctx.fillStyle = 'rgba(0, 0, 0, 0.05)'; // Sets a semi-transparent black fill to create a fading trail effect.
ctx.fillRect(0, 0, W, W); // Applies the semi-transparent fill, slightly clearing the canvas on each frame.

for (let i = 0; i < N; i++) {
for (let j = 0; j < N; j++) {
F(i, j); // Calls F function for each point, drawing the evolving pattern.
}
}

t += 0.2; // Increments the time variable, progressing the animation.
}

// Sets up an animation loop that updates and redraws the canvas at 60 frames per second.
return Generators.observe((notify) => {
const interval = setInterval(() => {
update(); // Calls the update function to redraw the canvas based on the current state.
notify(ctx.canvas); // Notifies ObservableHQ to update the canvas display.
}, 1000 / 60); // Aims for 60 updates per second.

// Provides a cleanup mechanism to clear the interval when the cell is re-evaluated.
return () => clearInterval(interval);
});
}

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