The story of d3 and the Start and End event listeners.

One of the cool things about d3 is that we can “listen” for transition events.

These listeners can be very useful things.

I’ll go through two of these in this blog post: start, and end. The use of these is best explained through examples.

Let’s start with the start listener (ha!).

Start listeners Link to heading

One use of a start listener is to trigger a function to run at the start of a transition.

Let’s set up a circle to use as an example:

var svg  = d3.select("body").append("svg")
			.attr("height", 500)
			.attr("width", 800);

svg.append("circle")
	.attr("cx", 100)
	.attr("cy",100)
	.attr("r", 10)
	.style("fill", "black");

Changing the colour of the black circle to blue is easy:

d3.select("circle")
	.transition()
	.delay(750)
	.style("fill", "blue");	

What if we wanted to change the colour of the black circle from green to blue? That is:

  • Start with a black circle
  • When the transition starts, immediately change to a green circle
  • Transition into a blue circle

Enter: the d3 start listener.

We “listen” for the transition, and when it begins, we can trigger a function through the use of selection.each. In this case, our function will be to change the colour of the circle from black to green. The transition will then kick in and change the colour of the circle from green to blue over a time period.

d3.select("circle")
	.transition()
	.delay(750)
	.each("start", function() {d3.select(this).style("fill", "green");    } )
	.style("fill", "blue");

Hang on - did that change anything?

Right. We should make the transition longer so that we can actually see the results:

d3.select("circle")
	.transition()
	.delay(750)
	.duration(3000)
	.each("start", function() {d3.select(this).style("fill", "green");    } )
	.style("fill", "blue");

That did it!

End listeners Link to heading

To stave off boredom, we will now move to changing the radius of the circle instead of the colour.

Let’s say we want to:

  • Start with a circle of radius 10
  • Jump to a circle of radius 80
  • Transition to a circle of radius 10
  • Jump back to a circle of radius 80

We can do this by utilising the listener for the end event. This will allow us to specify a function that will execute when the transition finishes.

d3.select("circle")
	.transition()
	.delay(750)
	.duration(1000)
	.each("start", function() {d3.select(this).attr("r", "80");    } )
	.attr("r", 10)
	.each("end", function() {d3.select(this).attr("r", "80")} );

To summarise Link to heading

Use start listeners to run a function right before a transition starts.

Use end listeners to run a function right after a transition ends.