Published
Edited
Aug 19, 2020
3 stars
Insert cell
Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

Insert cell
n = 9 // 2520/7/5
Insert cell
canvas = {
var t=0
const context = DOM.context2d(width, height);

const particles = new Array(n); // x2 if you want bi-directional
for (let i = 0; i < n; ++i) {
//let [r,g,b] = hslToRgb(i/n, .5 , 0.1)
let r = brightness* (1-(i+0)%3) //
let g = brightness* (1-(i+1)%3) //
let b = brightness* (1-(i+2)%3) //
particles[i] = {
x: 0,// Math.random() * width,
y: 0, // Math.random() * height,
vx: 0,
vy: 0,
rgb: [r,g,b].join()
};
}
//let t=0
context.globalCompositeOperation = "lighten"; //lighter, lighten, screen, overlay
var centerX=width/2
var centerY=height/2
while (true) {
context.save();
context.clearRect(0, 0, width, height);
context.beginPath();
//context.fillStyle = '#000';
context.fillRect(0, 0, width, height);
for (let i = 0; i < n; ++i) {
const p = particles[i];
let r= radius // *(n-i)/n
p.x = centerX + (r) * Math.sin(2*Math.PI*t*(i+1)/n)
p.y = centerY - (r) * Math.cos(2*Math.PI*t*(i+1)/n)
let alpha = .9
if(true) {
var gradient = context.createRadialGradient(p.x, p.y, 1, p.x, p.y, radius);
gradient.addColorStop(1, `rgba(0,0,0, ${alpha})`);
gradient.addColorStop(0, `rgba(${p.rgb},${alpha})`);
context.fillStyle = gradient // `rgb(${p.rgb})`

//context.fillStyle = `rgba(${p.rgb}, ${alpha})`

context.beginPath();
context.arc(p.x, p.y, radius, 0, 2 * Math.PI);
context.fill();
}
}

// mirror particles
if(false)
for (let i = n; i < n; ++i) {
const p = particles[i];
let r= centerX*(2*n-i)/n
p.x = centerX + r * Math.sin(-t*(i-n+1)/n)
p.y = centerY + r * Math.cos(-t*(i-n+1)/n)

var gradient = context.createRadialGradient(p.x, p.y, 1, p.x, p.y, radius);
let alpha= (i-n)/n
gradient.addColorStop(1, `rgba(0,0,0, ${alpha})`);
gradient.addColorStop(0, `rgba(${p.rgb},${alpha})`);

context.fillStyle = gradient // `rgb(${p.rgb})`

context.beginPath();
context.arc(p.x, p.y, radius, 0, 2 * Math.PI);
context.fill();
}
// lines between balls!
if( true ) {
for (let i = 0; i < n; ++i) {
for (let j = i ; j < n; ++j) {
const pi = particles[i];
const pj = particles[j];

//if( j%i === 0 || i%j===0) {
let alpha= 1 // .1 // (i-n)/n
//let [r,g,b] = hslToRgb(i/n, .5 , .1 )
//context.strokeStyle = `rgb(${r},${g},${b})`
context.strokeStyle = `rgba(255,255,255,${alpha})`
//context.strokeStyle = `rgba(${pi.rgb},${alpha})`
// context.globalAlpha = d2 > minDistance2 ? (maxDistance2 - d2) / (maxDistance2 - minDistance2) : 1;
context.lineWidth = 5// (i)/n
context.beginPath();
context.moveTo(pi.x, pi.y);
context.lineTo(pj.x, pj.y);
context.stroke();
//}
}
}
}
t+= speed / 100

context.restore();
yield context.canvas;
}
}
Insert cell
height = 1000
Insert cell
radius = 250
Insert cell
speed= 1/n*1
Insert cell
brightness = 255
Insert cell
Insert cell
hslToRgb(1,.5,.5)
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