Published
Edited
Apr 26, 2020
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
seed = Date.now()
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
colorScale = randomProc()
Insert cell
Insert cell
viewof gif = {
const gif = new GIF()
const canvas = DOM.canvas(w, h)
const context = canvas.getContext('2d')
const gradients = array(ny).map(i => {
const gradient = context.createLinearGradient(0, h / 2, w, h / 2)
array(nx[i]).forEach((d, j, arr) => {
gradient.addColorStop(j / (arr.length - 1), colorScale(random()))
})
return gradient
})
context.shadowColor = 'black'
context.shadowBlur = 15

for (let t = 0, nFrames = 60; t < nFrames; t++) {
const xt = Math.cos(t / nFrames * TAU) * moveAmp
const yt = Math.sin(t / nFrames * TAU) * moveAmp
context.fillStyle = 'black'
context.fillRect(0, 0, w, h)
// context.strokeStyle = 'none'
array(ny).forEach(i => {
const Y = (h + 200) / (ny - 1) * i - 100
let x = 0
let y = Y + simplex.noise3D(x / noiseScale + xt, Y / noiseScale + yt, seed) * amp
const step = w / nx[i]

context.fillStyle = gradients[i]
context.beginPath()
context.moveTo(-10, h + 200)
context.lineTo(0, y)
array(nx[i]).forEach(() => {
let px = x
x = x + step
let py = y
y = Y + simplex.noise3D(x / noiseScale + xt, Y / noiseScale + yt, seed) * amp
context.bezierCurveTo(px + step / 4, py, x - step / 4, y, x, y)
})
context.lineTo(w + 10, h + 200)
context.closePath()
context.fill()
})

gif.addFrame(canvas, { copy: true, delay: 120, quality: 1 })
yield canvas;
}
gif.on('finished', blob => {
canvas.value = blob
canvas.dispatchEvent(new CustomEvent('input'))
})
gif.render()
}
Insert cell
DOM.download(gif)
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