Public
Edited
Jan 2, 2023
Insert cell
Insert cell
Insert cell
Insert cell
N = 10 + Math.floor(Math.random() * 80)
Insert cell
Insert cell
class Box {
constructor(i, n) {
this.radius = 430;
this.w = map(i, 0, n - 1, 50, 150);
this.startAngle = random(TAU);
this.endAngle = this.startAngle + expRand(PI / 6, PI / 2);
this.black = random() < 0.75;
this.offset = random();
this.rot = random(TAU);
}

display(s, t, g) {
const tt = (t + this.offset) % 1;

const endAngle =
this.startAngle +
easings.easeQuadInOut(linearstep(tt, 0, 0.3)) *
(this.endAngle - this.startAngle);
const startAngle =
this.startAngle +
easings.easeQuadInOut(linearstep(tt, 0.35, 0.65)) *
(this.endAngle - this.startAngle);

if (endAngle - startAngle > 0.001) {
const white = 255;
const n = ((endAngle - startAngle) / 0.05) | 0;
const angles = array(n).map((i) =>
map(i, 0, n - 1, startAngle, endAngle)
);
const coses = array(n).map((i) => s.cos(angles[i]));
const sines = array(n).map((i) => s.sin(angles[i]));
s.push();

s.noStroke();
s.fill(this.black ? 150 : white);

s.beginShape(s.QUADS);
s.vertex(
coses[0] * (this.radius - this.w / 2),
-this.w / 2,
sines[0] * (this.radius - this.w / 2)
);
s.vertex(
coses[0] * (this.radius + this.w / 2),
-this.w / 2,
sines[0] * (this.radius + this.w / 2)
);
s.vertex(
coses[0] * (this.radius + this.w / 2),
+this.w / 2,
sines[0] * (this.radius + this.w / 2)
);
s.vertex(
coses[0] * (this.radius - this.w / 2),
+this.w / 2,
sines[0] * (this.radius - this.w / 2)
);
s.endShape();

s.beginShape(s.QUADS);
s.vertex(
coses[n - 1] * (this.radius - this.w / 2),
-this.w / 2,
sines[n - 1] * (this.radius - this.w / 2)
);
s.vertex(
coses[n - 1] * (this.radius + this.w / 2),
-this.w / 2,
sines[n - 1] * (this.radius + this.w / 2)
);
s.vertex(
coses[n - 1] * (this.radius + this.w / 2),
+this.w / 2,
sines[n - 1] * (this.radius + this.w / 2)
);
s.vertex(
coses[n - 1] * (this.radius - this.w / 2),
+this.w / 2,
sines[n - 1] * (this.radius - this.w / 2)
);
s.endShape();

//top
s.beginShape(s.TRIANGLE_STRIP);
array(n).forEach((i) => {
s.vertex(
coses[i] * (this.radius - this.w / 2),
-this.w / 2,
sines[i] * (this.radius - this.w / 2)
);
s.vertex(
coses[i] * (this.radius + this.w / 2),
-this.w / 2,
sines[i] * (this.radius + this.w / 2)
);
});
s.endShape();

//bottom
s.beginShape(s.TRIANGLE_STRIP);
array(n).forEach((i) => {
s.vertex(
coses[i] * (this.radius - this.w / 2),
+this.w / 2,
sines[i] * (this.radius - this.w / 2)
);
s.vertex(
coses[i] * (this.radius + this.w / 2),
+this.w / 2,
sines[i] * (this.radius + this.w / 2)
);
});
s.endShape();

//inner
s.beginShape(s.TRIANGLE_STRIP);
array(n).forEach((i) => {
s.vertex(
coses[i] * (this.radius - this.w / 2),
+this.w / 2,
sines[i] * (this.radius - this.w / 2)
);
s.vertex(
coses[i] * (this.radius - this.w / 2),
-this.w / 2,
sines[i] * (this.radius - this.w / 2)
);
});
s.endShape();

//outer
s.beginShape(s.TRIANGLE_STRIP);
array(n).forEach((i) => {
s.vertex(
coses[i] * (this.radius + this.w / 2),
+this.w / 2,
sines[i] * (this.radius + this.w / 2)
);
s.vertex(
coses[i] * (this.radius + this.w / 2),
-this.w / 2,
sines[i] * (this.radius + this.w / 2)
);
});
s.endShape();

s.noFill();
s.strokeWeight(7);
s.stroke(this.black ? white : 30);

const m = 0;

s.beginShape();
s.vertex(
coses[0] * (this.radius - (this.w / 2 + m)),
-(this.w / 2 + m),
sines[0] * (this.radius - (this.w / 2 + m))
);
s.vertex(
coses[0] * (this.radius + (this.w / 2 + m)),
-(this.w / 2 + m),
sines[0] * (this.radius + (this.w / 2 + m))
);
s.vertex(
coses[0] * (this.radius + (this.w / 2 + m)),
+(this.w / 2 + m),
sines[0] * (this.radius + (this.w / 2 + m))
);
s.vertex(
coses[0] * (this.radius - (this.w / 2 + m)),
+(this.w / 2 + m),
sines[0] * (this.radius - (this.w / 2 + m))
);
s.endShape(s.CLOSE);

s.beginShape();
s.vertex(
coses[n - 1] * (this.radius - (this.w / 2 + m)),
-(this.w / 2 + m),
sines[n - 1] * (this.radius - (this.w / 2 + m))
);
s.vertex(
coses[n - 1] * (this.radius + (this.w / 2 + m)),
-(this.w / 2 + m),
sines[n - 1] * (this.radius + (this.w / 2 + m))
);
s.vertex(
coses[n - 1] * (this.radius + (this.w / 2 + m)),
+(this.w / 2 + m),
sines[n - 1] * (this.radius + (this.w / 2 + m))
);
s.vertex(
coses[n - 1] * (this.radius - (this.w / 2 + m)),
+(this.w / 2 + m),
sines[n - 1] * (this.radius - (this.w / 2 + m))
);
s.endShape(s.CLOSE);

//top
s.beginShape();
array(n).forEach((i) => {
s.vertex(
coses[i] * (this.radius - (this.w / 2 + m)),
-(this.w / 2 + m),
sines[i] * (this.radius - (this.w / 2 + m))
);
});
s.endShape();

s.beginShape();
array(n).forEach((i) => {
s.vertex(
coses[i] * (this.radius + (this.w / 2 + m)),
-(this.w / 2 + m),
sines[i] * (this.radius + (this.w / 2 + m))
);
});
s.endShape();

//bottom
s.beginShape();
array(n).forEach((i) => {
s.vertex(
coses[i] * (this.radius - (this.w / 2 + m)),
+(this.w / 2 + m),
sines[i] * (this.radius - (this.w / 2 + m))
);
});
s.endShape();

s.beginShape();
array(n).forEach((i) => {
s.vertex(
coses[i] * (this.radius + (this.w / 2 + m)),
+(this.w / 2 + m),
sines[i] * (this.radius + (this.w / 2 + m))
);
});
s.endShape();
s.noStroke();
s.pop();
}
}
}
Insert cell
html`<style>
canvas, img {
max-width: ${width}px !important;
max-height: ${width}px !important;
}
</style>`
Insert cell
Insert cell
Insert cell
Insert cell
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