Simple animated graph
Posted .
Using transitions we can easily animate a graph. In this example we will be sampling a multivariate normal distribution for our data points.
Here is the source of the final graph (and the source of the fallback).
Sampling
We will not cover how to generate samples from a multivariate normal distribution. Assume there exists a sample
function that can do the following.
let s = sample()
console.log(s)
//{
// x: -1.338422862851693,
// y: -0.2415765924800481,
// p: 0.16190472411102744
//}
If you want to know how we did this you can reference the source code.
Colour scale
There are a whole lot of different color schemes available in d3. There are various interpolate functions that map the [0, 1]
domain onto a range of colours, we will be using the d3.interpolateRdYlBu
to map probabilities onto a colour scale. Alternatively you could reference the various scheme arrays when defining the range of a scale. These arrays contain arrays of colours themselves. So d3.schemeRdBu[k]
returns an array of length k
with colours ranging from red to blue, the size k
can range from 3 to 11.
Transitions
First we need to define a transition, unless you are satisfied with the defaults.
var t = d3.transition()
.duration(300) // default 250ms
.ease(d3.easeLinear) // default d3.easeCubic
Then we need to use it while setting an attribute of an element by calling the transition
method. Here we place a circle at 100x100
and have it grow from a radius of 0 to a radius of 10 over 300ms.
svg.append("circle")
.attr("transform", "translate(100, 100"")
.transition(t)
.attr("r", 10)
If we had placed the transition before setting the transform the transform would have been animated as well. You can delay a transition by calling the delay
method with number of milliseconds as a parameter.
Animation
By combining the things described above we can create a draw
function that draws a circle at a random location (determined by a multivariate normal distribution), gives it a colour corresponding to its probability, and fades it into and out of existence.
function draw() {
let s = sample()
var t = d3.transition()
.duration(800)
.ease(d3.easeLinear);
graph.append("circle")
.attr("transform", `translate(${x(s.x)}, ${y(s.y)})`)
.attr("fill", d3.interpolateRdYlBu(s.p))
.transition(t)
.attr("r", 3)
.transition(t)
.delay(400)
.attr("r", 0)
.remove()
}
Then we can use the setInterval
function to call the draw
function at 20ms intervals.
setInterval(draw, 20)
The result is an animated graph that shows a cloud of 100 samples of the distribution all randomly fading into and out of existence. See fig. 1.