Public
Edited
Jan 1, 2023
2 forks
5 stars
Also listed in…
loops
Insert cell
Insert cell
Insert cell
Insert cell
N = 60
Insert cell
bnb({
w,
h,
numFrames: 40,
fps: 20,
record: true,
// loops: 2,
// video: 'mp4',
shutterAngle: 0.3,
samplesPerFrame: 8,
// chromaticAberration: .6,

preload: (s, g) => {
g.pg1 = s.createGraphics(w, h, s.WEBGL)
g.pg1.setAttributes({alpha: true})
g.pg1.ortho()
g.pg1.camera(0, -280, 280, 0, 0, 0)
g.pg2 = s.createGraphics(w, h, s.WEBGL)
g.pg2.setAttributes({alpha: true})
g.pg2.ortho()
g.pg2.camera(0, -280, 280, 0, 0, 0)
g.boxes = array(N).map((i) => new Box(i, N))
g.pg3 = s.createGraphics(w, h, s.WEBGL)
g.pg3.setAttributes({alpha: true})
g.pg4 = s.createGraphics(w, h)
g.pg4.setAttributes({alpha: true})
},

draw: (s, t, g) => {
g.pg1.clear()
g.pg1.push()
g.boxes.forEach((b) => b.display(g.pg1, t, g))
g.pg1.pop()

g.pg2.clear()
g.pg2.push()
g.pg2.rotateX(-PI / 2)
g.boxes.forEach((b) => b.display(g.pg2, t, g))
g.pg2.pop()

g.pg3.clear()
g.pg3.push()
g.pg3.translate(s.sin(TAU * t) * 590, 0, 0)
g.pg3.rotateZ(.2)
g.pg3.rotateX(t * TAU)
g.pg3.rotateZ(-t * PI)
g.pg3.fill(30)
g.pg3.stroke(250)
g.pg3.strokeWeight(3)
displaySolid(g.pg3, icosahedron, 350 - s.sin(TAU * t * 2 + PI/4) * 50)
g.pg3.pop()

g.pg4.clear()
g.pg4.push()
//rotate PGraphics from center of canvas
g.pg4.translate(w / 2, h / 2)
g.pg4.rotate(PI / 2)
g.pg4.translate(-w / 2, -h / 2)
// display half of PGraphics
g.pg4.image(g.pg1, 0, 0, w / 2, h, 0, 0, w / 2, h)
g.pg4.image(g.pg2, w / 2, 0, w / 2, h, w / 2, 0, w / 2, h)
g.pg4.pop()

// erase artifacts
g.pg4.erase()
g.pg4.ellipse(w/2, h/2, 200, 200)
g.pg4.noErase()

s.background(30)
if(t < .25 || t > .75) {
s.image(g.pg4, 0, 0, w / 2, h, 0, 0, w / 2, h)
s.image(g.pg3, 0, 0)
s.image(g.pg4, w / 2, 0, w / 2, h, w / 2, 0, w / 2, h)
}
else {
s.image(g.pg4, w / 2, 0, w / 2, h, w / 2, 0, w / 2, h)
s.image(g.pg3, 0, 0)
s.image(g.pg4, 0, 0, w / 2, h, 0, 0, w / 2, h)
}

}
})
Insert cell
class Box {
constructor(i, n) {
this.radius = 350
this.w = map(i, 0, n - 1, 80, 180)
this.startAngle = random(TAU)
this.endAngle = this.startAngle + expRand(PI / 6, PI / 2)
this.black = random() < 0.5
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.25)) *
(this.endAngle - this.startAngle)
const startAngle =
this.startAngle +
easings.easeQuadInOut(linearstep(tt, 0.3, 0.55)) *
(this.endAngle - this.startAngle)

if (endAngle - startAngle > 0.001) {
const white = 250
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 ? 30 : white)

const nn = 8
s.beginShape()
for(let i = 0; i < nn; i ++) {
let angle = i/nn * TAU + PI/4
s.vertex(
coses[0] * (this.radius + s.sin(angle)*this.w / 2),
s.cos(angle)*this.w / 2,
sines[0] * (this.radius + s.sin(angle)*this.w / 2)
)
}
s.endShape(s.CLOSE)
s.beginShape()
for(let i = 0; i < nn; i ++) {
let angle = i/nn * TAU + PI/4
s.vertex(
coses[1] * (this.radius + s.sin(angle)*this.w / 2),
s.cos(angle)*this.w / 2,
sines[1] * (this.radius + s.sin(angle)*this.w / 2)
)
}
s.endShape(s.CLOSE)
for(let j = 0; j < nn; j ++) {
const angle = j / nn * TAU + PI/4
const angle2 = (j+1) / nn * TAU + PI/4
s.beginShape(s.TRIANGLE_STRIP)
array(n).forEach((i) => {
s.vertex(
coses[i] * (this.radius + s.sin(angle)*this.w / 2),
+ s.cos(angle)*this.w / 2,
sines[i] * (this.radius + s.sin(angle)*this.w / 2)
)
s.vertex(
coses[i] * (this.radius + s.sin(angle2)*this.w / 2),
+ s.cos(angle2)*this.w / 2,
sines[i] * (this.radius + s.sin(angle2)*this.w / 2)
)
})
s.endShape()
}

s.noFill()
s.strokeWeight(7)
s.stroke(this.black ? white : 30)
s.beginShape()
for(let i = 0; i < nn; i ++) {
let angle = i/nn * TAU + PI/4
s.vertex(
coses[0] * (this.radius + s.sin(angle)*this.w / 2),
s.cos(angle)*this.w / 2,
sines[0] * (this.radius + s.sin(angle)*this.w / 2)
)
}
s.endShape(s.CLOSE)
s.beginShape()
for(let i = 0; i < nn; i ++) {
let angle = i/nn * TAU + PI/4
s.vertex(
coses[n - 1] * (this.radius + s.sin(angle)*this.w / 2),
s.cos(angle)*this.w / 2,
sines[n - 1] * (this.radius + s.sin(angle)*this.w / 2)
)
}
s.endShape(s.CLOSE)
for(let j = 0; j < nn; j ++) {
const angle = j / nn * TAU + PI/4
s.beginShape()
array(n).forEach((i) => {
s.vertex(
coses[i] * (this.radius + s.sin(angle)*this.w / 2),
+ s.cos(angle)*this.w / 2,
sines[i] * (this.radius + s.sin(angle)*this.w / 2)
)
})
s.endShape()
}
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
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