Public
Edited
Oct 25, 2022
15 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
palette1 = utils.random.pick(palettes)
Insert cell
Insert cell
circleAnimation = {
const width = 1200
const height = 300
const ctx = DOM.context2d(width, height);
const numPoints = 200

// Pick a random palette for end data
const palette2 = utils.random.pick(palettes)

///////////////////////////////
///////// Create Data /////////
///////////////////////////////
const dataStart = _.range(0, numPoints).map(i => ({
id: i,
x: Math.random()*width,
y: Math.random()*height,
r: Math.abs(utils.random.gaussian() * 15),
fill: utils.random.pick(palette1)
}))

const dataEnd = _.range(0, numPoints).map(i => ({
id: i,
x: Math.random()*width,
y: Math.random()*height,
r: Math.abs(utils.random.gaussian() * 20),
fill: utils.random.pick(palette2)
}))


///////////////////////////////
//////// Draw Function ////////
///////////////////////////////

///////////////////////////////
////////// Animation //////////
///////////////////////////////


///////////////////////////////
//// Control the animation ////
///////////////////////////////
const play = document.querySelector('#play-circles')
const pause = document.querySelector('#pause-circles')
const restart = document.querySelector('#restart-circles')
const reverse = document.querySelector('#reverse-circles')

// play.onclick = () => animation.play()
// pause.onclick = () => animation.pause()
// restart.onclick = () => animation.restart()
// reverse.onclick = () => animation.reverse()


// Draw the initial graph

yield ctx.canvas
}
Insert cell
Insert cell
palette3 = utils.random.pick(palettes) // re-run this cell to update colours
Insert cell
viewof numCircles = Inputs.range([5000, 50000], {value: 20000, step: 5000, label: "Number of circles"})
Insert cell
Insert cell
manyCirclesAnimation = {
const width = 600
const height = 600
const ctx = DOM.context2d(width, height);
const numPoints = numCircles

// Pick a random palette for start and end data
const palette2 = utils.random.pick(palettes)

///////////////////////////////
///////// Create Data /////////
///////////////////////////////

///////////////////////////////
//////// Draw Function ////////
///////////////////////////////

///////////////////////////////
////////// Animation //////////
///////////////////////////////


///////////////////////////////
//// Control the animation ////
///////////////////////////////
const play = document.querySelector('#play-many')
const pause = document.querySelector('#pause-many')
const restart = document.querySelector('#restart-many')
const reverse = document.querySelector('#reverse-many')


// Draw the initial graph


yield ctx.canvas
}
Insert cell
Insert cell
palette4 = utils.random.pick(palettes) // re-run this cell to update colours
Insert cell
Insert cell
circlesToPackingAnimation = {
const width = 700
const height = 700
const ctx = DOM.context2d(width, height);
const numPoints = 4000

///////////////////////////////
///////// Create Data /////////
///////////////////////////////


///////////////////////////////
//////// Draw Function ////////
///////////////////////////////

///////////////////////////////
////////// Animation //////////
///////////////////////////////


///////////////////////////////
//// Control the animation ////
///////////////////////////////
const play = document.querySelector('#play-packing')
const pause = document.querySelector('#pause-packing')
const restart = document.querySelector('#restart-packing')
const reverse = document.querySelector('#reverse-packing')


// Draw the initial graph


yield ctx.canvas
}
Insert cell
Insert cell
Insert cell
Insert cell
circlesAnglesAnimation = {
const width = 1200
const height = 300
const ctx = DOM.context2d(width, height);
const numPoints = 1000

// Pick a random palette for start and end data
//const palette = utils.random.pick(palettes)

///////////////////////////////
///////// Create Data /////////
///////////////////////////////


///////////////////////////////
//////// Draw Function ////////
///////////////////////////////

///////////////////////////////
////////// Animation //////////
///////////////////////////////


///////////////////////////////
//// Control the animation ////
///////////////////////////////
const play = document.querySelector('#play-arc')
const pause = document.querySelector('#pause-arc')
const restart = document.querySelector('#restart-arc')
const reverse = document.querySelector('#reverse-arc')


// Draw the initial graph


yield ctx.canvas
}
Insert cell
Insert cell
Insert cell
circlesAnime = {
const width = 1000
const height = 1000
const ctx = DOM.context2d(width, height);


///////////////////////////////
///////// Create Data /////////
///////////////////////////////
const dataStart = getRandomArrangement(dataTidy, width, height)
const dataEnd = getCirclePacking(dataTidy, width, height)

///////////////////////////////
//////// Draw Function ////////
///////////////////////////////

///////////////////////////////
////////// Animation //////////
///////////////////////////////


///////////////////////////////
//// Control the animation ////
///////////////////////////////
const play = document.querySelector('#play-anime')
const pause = document.querySelector('#pause-anime')
const restart = document.querySelector('#restart-anime')
const reverse = document.querySelector('#reverse-anime')


// Draw the initial graph


yield ctx.canvas
}
Insert cell
function getRandomArrangement(dataIn, width, height) {
const dataRandomArrangement = _.range(0, dataIn.length - 1).map(i => ({
name: dataIn[i].name,
x: Math.random()*width,
y: Math.random()*height,
r: Math.abs(utils.random.gaussian() * 5),
fill: dataIn[i].fill,
red: dataIn[i].red,
green: dataIn[i].green,
blue: dataIn[i].blue,
}))
return dataRandomArrangement
}
Insert cell
function getCirclePacking(dataIn, width, height) {
const dataClone = _.cloneDeep([...dataIn])
const circlePacking = d3.packSiblings(dataClone).map(d => ({
x: d.x + width /2,
y: d.y + height / 2,
r: d.r,
fill: d.fill,
red: d.red,
green: d.green,
blue: d.blue,
}))
return circlePacking
}
Insert cell
dataTidy = tidyData(dataSample)
Insert cell
function tidyData(dataIn) {
const radius = 2.5
const data = []
dataIn.forEach(frame => {
frame.colours.forEach(colour => {
data.push({
name: frame.img,
fill: colour,
red: +colour.split(', ')[0].split('(')[1],
green: +colour.split(', ')[1],
blue: +colour.split(', ')[2].split(')')[0],
r: radius
})
})
})
return data
}
Insert cell
dataSample = dataRaw.filter((d, i) => i%5 === 0) // Take every 5th frame; you can change this to experiment.
Insert cell
dataRaw = spiritedAway
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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