Published
Edited
Oct 11, 2021
2 stars
Insert cell
Insert cell
{
const width = 600
const height = 600
const canvas = html`<canvas width = ${width} height = ${height} style = "border:black 1px solid;">`
const ctx = canvas.getContext("2d")

//animation parameters
const segSize = 10
const stepSize = 10
const framesPerTick = segSize/stepSize
const numTicks = 100

//make walkers
const walkers = []
for(let i = 0; i < 500; i = i + 1){
const props = {
ctx:ctx,
x: d3.randomUniform(0,width)(),
y: d3.randomUniform(0,height)()
}
const walker = new Walker(props)
walkers.push(walker)
}

const crowd = new Crowd({ctx:ctx,walkers:walkers})

//initialize animation
let frame = 0
let tick = 0

//loop
function loop(){
crowd.step(stepSize)
if(frame%framesPerTick==0){
crowd.changeTheta()
tick = tick + 1
}
if(tick < numTicks){
frame = frame + 1
window.requestAnimationFrame(loop)
}
}

//run animation
window.requestAnimationFrame(loop)


return canvas
}
Insert cell
class Walker{
constructor(props){
this.ctx = props.ctx
this.x = props.x
this.y = props.y

this.theta = d3.randomUniform(0,2*Math.PI)()
}

step(stepSize){
this.ctx.beginPath()
this.ctx.moveTo(this.x,this.y)
this.x = this.x + stepSize*Math.cos(this.theta)
this.y = this.y + stepSize*Math.sin(this.theta)
this.ctx.lineTo(this.x,this.y)
this.ctx.stroke()
this.ctx.closePath()
}

changeTheta(){
this.theta = d3.randomUniform(0,2*Math.PI)()
}
}
Insert cell
class Crowd{
constructor(props){
this.ctx = props.ctx
this.walkers = props.walkers
}

step(stepSize){
this.walkers.map(w => w.step(stepSize))
}

changeTheta(){
this.walkers.map(w => w.changeTheta())
}
}
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