Visualisation with D3.js

A practical book on visualisation with D3.js that shows you how to create visualisations from the ground up that are engaging and beautiful.

Get the book
Colour Transitions

Preamble

Let's get access to the D3.js library so that we can begin. In this case, we'll be including the library using the HTML <script> tag.

<script src="https://d3js.org/d3.v7.js"></script>

Introduction

The last few sections on animated transitions have focussed manipulating the geometric properties of various SVG shape elements1. In this section, we'll look at how we can use transitions and styling properties to animate the colour of SVG shape elements.

Let's use D3js to transition a circle starting from the colour magenta.

<svg>
    <circle fill="magenta" cx="150" cy="75" r="50"></circle>
</svg>

Which will then gradually turn to the colour cyan.

<svg>
    <circle fill="cyan" cx="150" cy="75" r="50"></circle>
</svg>

We'll also make use of an easing function to make the transitions more interesting. These two transitions will occur one after another without any condition for termination, i.e. forever!

A Container for the Output

This is where you will see the output of the code cells that follow it, provided they are referencing the corresponding id.

<div id="container"></div>

Creating an Empty SVG

We'll create a new detached <svg> element and use the returned selection throughout the rest of this section.

svg = d3.create("svg");

Creating a Circle Element

Let's create our circle! We'll append the <circle> element to our selection of the <svg> element, and we'll give it a fill colour of magenta using the style attribute, .style("fill", "magenta");. Whilst we could use the string literal magenta as our argument to change the fill colour, we'll use its hexadecimal equivalent, #ff00ff instead. This will give us more opportunity should we want to tinker with the colours. We could also use an RGB value, e.g. rgb(255, 0, 255).

var circle = svg
    .append("circle")
    .attr("cx", 150)
    .attr("cy", 75)
    .attr("r", 50)
    .style("fill", "#ff00ff");

Animating the Circle Colour with Easing

Let's create two functions, one to colour our circle magenta, and another to colour it cyan. This will be similar to previous sections where we've expanded a circle with something much like the following:

function expandCircle() {
    circle
        .transition()
        .ease(d3.easePoly)
        .duration(1000)
        .attr('r', 75)
        .on('end', contractCircle);
}

Except, this time we won't be changing the geometric properties of our circle.

Function to Colour the Circle Magenta

We'll start with the function to colour the circle magenta, which we'll name colourMagenta().

function colourMagenta() {
    circle
        .transition()
        .ease(d3.easePoly)
        .duration(2000)
        .style("fill", "#ff00ff")
        .on('end', colourCyan);
}

When this transition ends, it will call the colourCyan() function which doesn't exist just yet.

Function to Colour the Circle Cyan

Let's create our missing function to colour the circle cyan, which we'll name colourCyan().

function colourCyan() {
    circle
        .transition()
        .ease(d3.easeBounce)
        .duration(2000)
        .style("fill", "#00ffff")
        .on('end', colourMagenta);
}

This time, we can see we've added a listener function to call colourMagenta() when the transition ends.

Starting the Animation

The code that handles our transitions now appears within two functions. That means that nothing will happen on page load unless we invoke one of these functions directly to kick everything off. Let's start our looping transitions by invoking colourMagenta(), which will call colourCyan() when it ends, and so on!

colourMagenta();

Appending to the Container

Finally, let's append everything to our container.

d3
    .select("#container")
    .append(() => svg.node());

We can see the output by checking on our container with the corresponding id, which in this case is where id=container.

Conclusion

If we inspect the HTML, we will see the <svg> and <circle> elements have been added to the <div> where the id=container. We can also see that the <circle> element's style attribute includes a fill that is gradually changing between magenta (style="fill: rgb(255, 0, 255)") and cyan (style="fill: rgb(0, 255, 255)").

<div id="container">
  <svg>
    <circle cx="150" cy="75" r="50" style="fill: rgb(255, 0, 255);"></circle>
  </svg>
</div>

  1. W3C. Geometry Properties, https://www.w3.org/TR/SVG2/geometry.html. 

Comments

From the collection

Visualisation with D3.js

A practical book on visualisation with D3.js that shows you how to create visualisations from the ground up that are engaging and beautiful.

Get the book

ISBN

978-1-915907-05-9

Cite

Rostami, S. (2022). Visualisation with D3.js. Polyra Publishing.