Public
Edited
Mar 22, 2023
Insert cell
Insert cell
Insert cell
nodes = [{id: 0, name: "A"}, {id: 1, name: "B"}, {id: 2, name: "C"}, {id:3, name: "D"}]
Insert cell
Insert cell
Insert cell
margin = ({top: 20, bottom: 20, left: 30, right: 30});
Insert cell
height = 300 - margin.top - margin.bottom;
Insert cell
Insert cell
Insert cell
xScale = d3.scalePoint()
.domain(nodesNames)
.range([0,width])
Insert cell
yScale = d3.scalePoint()
.domain(nodesNames)
.range([0,height])
Insert cell
Insert cell
// Adapted from https://www.d3-graph-gallery.com/graph/arc_basic.html
justNodesAndLabels = {
const radius = 8
// create a container for the svg; use standard margin notation
const container = d3.select(DOM.svg(width+margin.left+margin.right,
height+margin.top+margin.bottom))
// create a group to hold the viz, adjust the coordinates using standard margin notation
const arcGroup = container
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
// create the nodes and labels similarly to Lab 1;
// the new part here is that x locations are determined by the xScale function;
// we also add some padding to y to move it away from the margins
// we assign an attribute named id, as this can be useful to have later
arcGroup.selectAll("nodes")
.data(nodes)
.enter().append("circle")
.attr("cx", d => xScale(d.name))
.attr("cy", height-50)
.attr("r", radius)
.attr("fill", "steelblue")
.attr("id", d => d.id)
arcGroup.selectAll("nodeLabels")
.data(nodes)
.enter().append("text")
.attr("x", d => xScale(d.name))
.attr("y", height-20)
.attr("fill", "darkgrey")
.style("text-anchor", "middle")
.text(d => d.name)
return container.node();
}
Insert cell
Insert cell
// code goes here
Insert cell
Insert cell
animatedNodes1 = {
const radius = 8
const container = d3.select(DOM.svg(width+margin.left+margin.right,
height+margin.top+margin.bottom))
const arcGroup = container
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
// First place the nodes at cy position 50
// Then call transition(), with a duration of i*500, moving to cy position height-50
// For fun, we've put in a bouncing ease transition type. Try changing it around!
const animatedNodes = arcGroup.selectAll("nodes")
.data(nodes)
.enter().append("circle")
.attr("cx", d => xScale(d.name))
.attr("cy", 50)
.attr("r", radius)
.attr("fill", "steelblue")
.attr("id", d => d.id)
.transition()
.ease(d3.easeBounce)
.duration((d,i) => i*500)
.attr("cy", height-50);
return container.node()
}
Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

Insert cell
Insert cell
// code goes here
Insert cell
// code goes here
Insert cell
Insert cell
animatedNodes2 = {
const radius = 8
const container = d3.select(DOM.svg(width+margin.left+margin.right,
height+margin.top+margin.bottom))
const arcGroup = container
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
const animatedNodes = arcGroup.selectAll("nodes")
.data(nodes)
.enter().append("circle")
.attr("cx", d => xScale(d.name))
.attr("cy", 50)
.attr("r", radius)
.attr("fill", "steelblue")
.attr("id", d => d.id)
.transition()
.ease(d3.easeBounce)
.duration((d,i) => i*500)
.attr("cy", height-50);
/* This invokes additional transitions on the nodes selection;
Try commenting it out and putting it back in.
Add more transitions to the or in the middle. */
animatedNodes
.transition()
.attr("fill", "firebrick")
.transition()
.attr("cy", 50)
return container.node()
}
Insert cell
Insert cell
Insert cell
Insert cell
animatedNodesWithEnd = {
const radius = 8
const container = d3.select(DOM.svg(width+margin.left+margin.right,
height+margin.top+margin.bottom))
const arcGroup = container
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
// First place the nodes at cy position 50 and color green
// Then call transition(), with a duration of i*500, moving to cy position height-50
// For fun, we've put in a bouncing ease transition type. Try changing it around!
const animatedNodes = arcGroup.selectAll("nodes")
.data(nodes)
.enter().append("circle")
.attr("cx", d => xScale(d.name))
.attr("cy", 50)
.attr("r", radius)
.attr("fill", "firebrick")
.attr("id", d => d.id)
.transition()
.ease(d3.easeBounce)
.duration((d,i) => i*1000)
.attr("cy", height-50)
animatedNodes.transition()
.ease(d3.easeLinear)
.attr("fill", "steelblue")
.on("end", function (d, i) {
d3.select(this)
.transition()
.duration(1000)
.attr("cy", 50)
// .attr("r", 20) // solution to exercise
})
return container.node();
}
Insert cell
md`Exercise: add code to make the circles get larger after they change to their final positions.
`
Insert cell
// code goes here
Insert cell
Insert cell
expandingAnimatedNodes = {
const radius = 8
const container = d3.select(DOM.svg(width+margin.left+margin.right,
height+margin.top+margin.bottom))
// give the svg a black background
container.style("background-color", "black")
const arcGroup = container
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
// define a bright red color; used the color meter on the pitch interactive viz
const redcol = d3.rgb("252", "0", "8");
// first just place the red nodes at opacity 1
const animatedNodes = arcGroup.selectAll("nodes")
.data(nodes)
.enter().append("circle")
.attr("cx", d => xScale(d.name))
.attr("cy", height-50)
.attr("r", radius)
.attr("fill", redcol)
.attr("opacity", 1)

// now do the animations. Grow the size and then fade out the circles.
animatedNodes
.transition(d3.easeBounce)
.duration(1000)
.attr("r", 20).attr('opacity', 0.3)
.transition()
.ease(d3.easeLinear)
.duration(2000)
.attr("fill", "black")
return container.node();
}
Insert cell
expandingAnimatedNodes2 = {
const radius = 8
const container = d3.select(DOM.svg(width+margin.left+margin.right,
height+margin.top+margin.bottom))
// give the svg a black background
container.style("background-color", "white")
const arcGroup = container
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
// define a bright red color; used the color meter on the pitch interactive viz
const redcol = d3.rgb("252", "0", "8");
// first just place the red nodes at opacity 1
const animatedNodes = arcGroup.selectAll("nodes")
.data(nodes)
.enter().append("circle")
.attr("cx", d => xScale(d.name))
.attr("cy", height-50)
.attr("r", radius)
.attr("fill", redcol)
.attr("opacity", 1)
container.transition().duration(50).style("background-color", "black")

// now do the animations. Grow the size and then fade out the circles.
// at the end, fade the black background white.
animatedNodes
.transition(d3.easeBounce)
.duration(1000)
.attr("r", 20).attr('opacity', 0.3)
.transition()
.ease(d3.easeLinear)
.duration(2000)
.attr("opacity", 0)
.on("end", function() {
container.transition().duration(1000).style("background-color", "white");
})
return container.node();
}
Insert cell
Insert cell
d3 = require("d3@^5.8")
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