canvas = {
const div = document.createElement("div");
div.className = 'container'
const layer1 = DOM.context2d(w, w);
const layer2 = DOM.context2d(w, w);
const colors = d3.schemeSpectral[10];
div.append(layer1.canvas, layer2.canvas);
layer1.canvas.style.background = "hsl(216deg 20% 8%)";
layer2.textBaseline = 'ideographic'
layer2.textAlign = 'center'
layer2.font = `${radius}px serif`;
const headerDotSize = 40 / nOscillators;
const freqs = d3.range(1, nOscillators + 1).map(patternF)
const speed = -1e-2;
const prevPositions = {}
let counter = 0;
while (true) {
counter += 1;
layer2.fillStyle = "hsl(216deg 0% 83%)";
layer2.strokeStyle = "hsl(216deg 0% 83%)";
layer2.clearRect(0, 0, w, w);
freqs.forEach((freq, i) => {
layer2.globalAlpha = 1;
const offset = (gap + radius * 2) * (i + 1) + gap;
const position = radius + Math.sin(counter * speed * freq) * radius;
const compliment = radius + Math.cos(counter * speed * freq) * radius;
// X Header
layer2.beginPath();
layer2.arc(offset + radius, gap + radius, radius, 0, Math.PI * 2);
layer2.stroke();
// Number
layer2.beginPath();
layer2.fillText(freq, offset + radius, gap + radius * 1.5)
// Draw a circle at the position of the oscillator
layer2.beginPath();
layer2.arc(offset + position, gap + compliment, headerDotSize, 0, Math.PI * 2);
layer2.fill();
// Y Header
layer2.beginPath();
layer2.arc(gap + radius, offset + radius, radius, 0, Math.PI * 2);
layer2.stroke();
// Number
layer2.beginPath();
layer2.fillText(freq, gap + radius, offset + radius * 1.5)
// Draw a circle at the position of the oscillator
layer2.beginPath();
layer2.arc(
gap + position,
offset + compliment,
headerDotSize, 0, Math.PI * 2);
layer2.fill();
layer2.globalAlpha = 0.4;
// LineX
layer2.beginPath();
layer2.moveTo(offset + position, 0)
layer2.lineTo(offset + position, w)
layer2.stroke();
// LineY
layer2.beginPath();
layer2.moveTo(0, offset + compliment)
layer2.lineTo(w, offset + compliment)
layer2.stroke();
})
// draw our paint
freqs.forEach((freqX, i) => {
freqs.forEach((freqY, j) => {
// Pick a color
layer1.strokeStyle = colors[(i + j) % 10];
layer1.globalAlpha = 1
const offsetX = (gap + radius * 2) * (i + 1) + gap;
const offsetY = (gap + radius * 2) * (j + 1) + gap;
const position = radius + Math.sin(counter * speed * freqX) * radius;
const compliment = radius + Math.cos(counter * speed * freqY) * radius;
const [x, y] = [offsetX + position, offsetY + compliment];
const [prevX, prevY] = prevPositions[`${i},${j}`] ? prevPositions[`${i},${j}`] : [x,y];
// Our point (LAYER 1
layer1.beginPath();
layer1.moveTo(prevX, prevY);
layer1.lineTo(x, y);
layer1.stroke();
prevPositions[`${i},${j}`] = [x , y];
})
})
// Fade the canvas a bit
// layer1.globalAlpha = 0.01
// layer1.fillRect(0, 0, w, w)
yield div;
}
}