D3 Enter and Exit Concept

by

D3 is so awesome. The other day a friend showed me Spotify Serendipity project, which used D3, and I was floored by the beauty of how visual data can show so much. A picture is truly worth more than a thousand words.

Over a year ago, when I stumbled upon D3, I did not realize its power until I understood the Enter/Exit concept, in which I want to share in this post. In a simplified way, D3 manages a given dataset and determines what changed in the dataset. You will need to define what happens when a node (a DOM representation of a piece of data) is new or when a node has been removed. A new node “enters”, and a removed node “exits”.

Here is an example. Using an array of our own Grio folks, the dataset changes every second reshuffling the list and randomizing the number of people to pop from the list. You can view the JSFiddle demo here.

var Y_SPACING = 14;

var svg = d3.select('#d3-example').append('svg')
    .attr('width', 800)
    .attr('height', 600);

var grioites = ['Doug', 'Brad', 'Santo', 
   'Gert', 'Paolo', 'Giuseppe','Ryan', 
   'Martin', 'Eric', 'Meg', 'Robert', 
   'Jenny', 'Morgan', 'Ishwar', 'Paul', 
   'Adam K', 'Adam L', 'Kostas', 
   'Ian', 'Eleanor', 'Ozan', 'David',
   'Peter'
];

function refresh(people) {
    
    // Bind data to nodes. 
    // This is where the data set has been added, updated, deleted.
    var text = svg.selectAll('text')
        .data(people, function(d) { return d; });
    
    // Rule to handle existing node
    text.transition()
        .duration(750)
        .attr('y', function(d, i) { return Y_SPACING * i + Y_SPACING; })
        .style('fill-opacity', 1)
        .style('fill', 'black');
   
    // Rule to handle new node.
    text.enter().append('text')
        .attr('x', 0)
        .attr('y', -60)
        .style('fill-opacity', 0)
        .text(function(d, i) { return d; })
        .transition()
        .duration(750)
        .attr('y', function(d, i) { return Y_SPACING * i + Y_SPACING; })
        .style('fill-opacity', 1)
        .style('fill', 'blue');
    
    // Rule to handle deleted node
    text.exit()
        .attr('x', 0)
        .transition()
        .duration(750)
        .attr('x', 60)
        .style('fill-opacity', 0)
        .style('fill', "red")
        .remove();
}

// Initialize.
refresh(grioites);

// Shuffle data. Note: Used Underscore just for convenience
setInterval(function() {
    var shuffled = _.shuffle(grioites);
    refresh(_.first(shuffled, Math.floor(Math.random() * grioites.length)));
}, 1000);

In summary for each:
– node entering: node will be placed vertically based off of its index in the array, and colored blue.
– existing node: change its color to black, and reshuffle position based off of index.
– exited node: change the color to red, move horizontally right, and disappear.

The D3 community is very active and vibrant and the documentation is excellent. You can find more resources on D3 here.

Also for some very great reading is the D3 creator Mike Bostock’s IEEE InfoVis 2011 paper on D3.

Happy visualizing!

Leave a Reply

Your email address will not be published. Required fields are marked *