Binding object literals as data

With a more complex visualization, each element we have in a data array might not be a primitive integer value or a string, but a JavaScript object themselves. In this recipe, we will discuss how this more complex data structure can be leveraged to drive your visualization using D3.

Getting Ready

Open your local copy of the following file in your web browser:

https://github.com/NickQiZhu/d3-cookbook/blob/master/src/chapter3/object-as-data.html

How to do it...

JavaScript object literal is probably the most common data structure you will encounter when loading data sources on the Web. In this recipe, we will look at how these JavaScript objects can be leveraged to generate rich visualization. Here is how to do it in code:

var data = [ // <- A
        {width: 10, color: 23},{width: 15, color: 33},
        {width: 30, color: 40},{width: 50, color: 60},
        {width: 80, color: 22},{width: 65, color: 10},
        {width: 55, color: 5},{width: 30, color: 30},
        {width: 20, color: 60},{width: 10, color: 90},
        {width: 8, color: 10}
    ];
    
var colorScale = d3.scale.linear()
.domain([0, 100]).range(["#add8e6", "blue"]); // <- B

    function render(data) {
        d3.select("body").selectAll("div.h-bar")
            .data(data)
            .enter().append("div")
                .attr("class", "h-bar") 
            .append("span");

        d3.select("body").selectAll("div.h-bar")
            .data(data)
            .exit().remove();

        d3.select("body").selectAll("div.h-bar")
            .data(data)
                .attr("class", "h-bar")
                .style("width", function (d) { // <- C
                    return (d.width * 5) + "px"; // <- D
                })
                .style("background-color", function(d){
                    return colorScale(d.color); // <- E
                })
            .select("span")
                .text(function (d) {
                    return d.width; // <- F
                });
    }

    function randomValue() {
        return Math.round(Math.random() * 100);
    }

    setInterval(function () {
        data.shift();
        data.push({width: randomValue(), color: randomValue()});
        render(data);
    }, 1500);

    render(data);

This recipe generates the following visualization:

How to do it...

Data as Object

How it works...

In this recipe, instead of simple integers as in the previous recipe, now our data array is filled with objects (see the line marked as A with an arrow left to it). Each data object contains two attributes—width and color—that are both integers in this case.

Note

This recipe is built on top of the previous recipe so if you are not familiar with the fundamental enter-update-exit selection pattern, please review the previous recipe first.

var data = [ // <- A

        {width: 10, color: 23},{width: 15, color: 33},
...
        {width: 8, color: 10}
    ];

Note

On line B, we have a complicated-looking color scale defined. Scales, including color scale, will be discussed in depth in the next chapter, so for now let us just assume this is a scale function we can use to produce CSS-compatible color code given some integer input value. This is sufficient for the purpose of this recipe.

The major difference between this recipe and the previous one is how data is handled as shown on line C:

function (d) { // <- C
return (d.width * 5) + "px"; // <- D
}

As we can see in the preceding code snippet, in this recipe the datum associated with each visual element is actually an object, not an integer. Therefore, we can access the d.width attribute on line D.

Tip

If your object has functions of its own, you can also access them here in a dynamic modifier function. This is a convenient way to add some data-specific helper functions in your data source. However, beware that since dynamic functions are usually invoked numerous times during visualization, the function you rely on should be implemented as efficiently as possible. If this is not possible, then it is best to preprocess your data before binding them to your visualization process.

Similarly on line E, the background-color style can be computed using the d.color attribute with the color scale we defined earlier:

.style("background-color", function(d){
  return colorScale(d.color); // <- E
})
.select("span")
  .text(function (d) {
    return d.width; // <- F
  });

The child element span again inherits its parent's associated datum, and hence, it also has access to the same datum object in its dynamic modifier function on line F setting the textual content to d.width attribute.

This recipe demonstrates how JavaScript objects can easily be bound to visual elements using exactly the same method discussed in the previous recipe. This is one of the most powerful capabilities of the D3 library; it allows you to re-use the same pattern and method to handle different types of data, simple or complex. We will see more examples on this topic in the next recipe.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset