Friday, December 28, 2012

D3GL Tutorials 02: Binding data to each globe

So far we have discussed binding a dataset to a globe-rendering template, then creating multiple globes that utilize the template. But you also want to bind datasets per globe - you want color-coded maps, points, bars with different heights jutting out of the sphere, arcs stretching across oceans.

The elements of data - points, bars, etc. - we call data primitives. With
d3gl.globe
, we bind data per type of data primitive. That is, each globe can have multiple data primitives, and each data primitive type gets its own dataset to visualize. We will talk more about data primitives, their shared properties, and available user interactions in the next tutorial.

In this tutorial, we go over how you bind a different dataset to a data primitive on each globe.

Bind data to a primitive


var rainfall = [10, 0, 5, 20];
globe.points().data(rainfall);

In the above snippet of code, the variable
globe
is a globe template. We are creating the points layer on top of the globe, and telling it that a point should be rendered per data item in
[10, 0, 5, 20]
.

But let's not forget that the same globe template can be used to create multiple globes. With the above code, each globe rendered from the globe template will render points using the same dataset. We probably don't want that.

Bind different data to each globe


To pass in different datasets for globes using the same template, we can do the following:
var precipitation = {
  ‘rainfall’: [10, 0, 5, 20],
  ‘snowfall’: [0, 30, 0, 10]
};

// create a globe rendering template
var globe = d3.gl.globe()
  .width(300)
  .height(300)
  .texture("earth.jpg");

// add points, specify dataset for points
var points = globe.points()
  .data( function(d) {
    return precipitation[d];
  });

// render two globes
d3.select(“body”)
  .selectAll(“span”)
  .data(Object.keys(precipitation))
  .enter()
  .append(“span”)
  .call(globe);

This binds the array
['rainfall', 'snowfall']
to the globe rendering template with
.data(Object.keys(precipitation))
. Then each element in the array is passed in as a parameter to each of the two globes that are created with the template.

Because we added the
points
primitive to the globe template, each globe instance renders a points layer. The points on the globe that has the data element
'rainfall'
binds to the array
[10, 0, 5, 20]
, which it grabbed with its
data
property, as specified in the template:
.data( function(d) {
  return precipitation[d];
});

Likewise, the globe that is passed in
'snowfall'
binds its points to
[0, 30, 0, 10]
.

Demo


Since we haven't given
points
enough settings to be able to display the data, there will be no demo for this tutorial. To check out data-binding in action, you should continue on to the next tutorials that cover the different primitives you can bind data with!

Implementation


Like
d3.gl.globe
, the data primitives are closures with getters and setters. They have a rendering call, just like
d3.gl.globe
has a rendering call that is invoked with
.call(globe)
. But the rendering call for a data primitive type is invoked internally in the rendering loop started when the globes are rendered. Each rendering call for a primitive gets the data element assigned to the globe the primitive belongs to, which is then used to grab the relevant dataset.

The implementation for data primitives will be discussed more in depth in the next tutorial.

← Prev

No comments:

Post a Comment