Public
Edited
Aug 16, 2024
2 stars
Insert cell
Insert cell
Insert cell
data = {// Ctrl+S or Shift+Enter to update data to random positions
let w = 500
let h = 400
let array = [ {key:'orange-0', class:'orange', r:100, cx:250, cy:200} ] // center dot that doesn't change

for( let i=0; i<10; i++){ // Same points, but updates to a random position
array.push({key:'coral-' + i, class:'coral', r:50*Math.random(), cx:w*Math.random(), cy:h*Math.random()})
}
let n = Math.round(100 * Math.random()) // number of dots
for( let i=0; i<n; i++){ // always enters new points and exit old points
array.push({key:'lightpink-'+Math.random(), class:'lightpink', r:10+10*Math.random(), cx:w*Math.random(), cy:h*Math.random()})
}
return array
}
Insert cell
chart.input( data ) // Updates data without reloading the chart cell. Fires everytime the 'data' cell is run.
Insert cell
chart = {
// settings
let w=500, h=400;
let animationSpeed = 2000; // in miliseconds
let ease = d3.easeElasticOut.amplitude(1).period(0.3); // d3 includes a whole library of easing functions,

// create chart
const svg = d3.create("svg");
return Object.assign(svg.node(), {input(dataIn) { // this returns the SVG as an object with input() as a method for updating data
svg.attr("width", w).attr("height", h)

let dots = svg.selectAll("circle.dots") // selecting circles that have the 'dots' class. We have to add the class when each dot enters
.data(dataIn, d => d.key) // you have to have a unique key for each datapoint, or D3 will use the array index
.join(
enter => enter // when data with a new key is added
.append("circle")
.attr('class', d => 'dots' + ' ' + d.class) // we need a class name so D3 can select these circles and leave other circles on the page alone. This is also where you can add other classes for CSS styling, seperated by a space
// initial properties
.transition().duration(0)
.attr('cx', d => d.cx)
.attr('cy', d => d.cy)
.attr('r', 0 )
// animated properties
.transition().duration(animationSpeed).ease(ease)
.attr('r', d => d.r) // grows dot from point
,
update => update // when data with an existing key is updated
.attr('class', d => 'dots' + ' ' + d.class)
.transition().duration(animationSpeed).ease(ease)
.attr('cx', d => d.cx)
.attr('cy', d => d.cy)
.attr('r', d => d.r)
,
exit => exit // when the data array no longer includes an object's key
.transition().duration(animationSpeed).ease(ease)
.attr('r', 5) // shrinks dot
.remove() // removes object from scene
)
}})
}
Insert cell
<style> /* styling done outside JavaScript keeps the code simple and help makes changes accessible to devs who program in CSS */
circle.dots {
fill:steelblue;
opacity:.5;
}
circle.orange { fill:orange;}
circle.coral { fill:coral;}
circle.lightpink { fill:lightpink; opacity:.2; }
</style>
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