Skip to content

Latest commit

 

History

History

STEP 02

Goals:

  • Let's now turn the D3 chart into a module
  • The module contains all the D3 chart functions
  • Module should be updated with public getter/setter

Some notes:

  • Modules are plugins in D3 land, will be used interchangeably
  • Modules add / override functionalities

Turn the bar chart into a reusable chart

💡Reusable Charts is a convention for encapsulating reusable charts in D3.

Key parts are:

  • Implement charts as closures
  • Add getter-setter methods.

Here is the suggested re-usability template

function chart() {
  var width = 720, // default width
      height = 80; // default height

  function my() {
    // generate chart here, using `width` and `height`
  }

  my.width = function(value) {
    if (!arguments.length) return width;
    width = value;
    return my;
  };

  my.height = function(value) {
    if (!arguments.length) return height;
    height = value;
    return my;
  };

  return my;
}

To call the chart

var myChart = chart().width(720).height(80);

Selection as input for reusable chart

Now the selection part is needed to update the chart

🌶 By taking a selection as input, charts have greater flexibility. For example, you can render a chart into multiple elements simultaneously, or easily move a chart between elements without explicitly unbinding and rebinding. You can control exactly when and how the chart gets updated when data or configuration changes (for example, using a transition rather than an instantaneous update). In effect, the chart becomes a rubber stamp for rendering data visually.

function my(selection) {
  selection.each(function(d, i) {
    // generate chart here; `d` is the data and `this` is the element
  });
}

To call the chart

  d3.select("body")
      .datum(data)
      .call(chart);

Which is equivalent to

chart(d3.select("body").datum(data))

New data and chart update

Beside that, it's all d3-chart-building business as usually. The rest will indeed mainly making sure your chart is:

Let's make it robust to new data.

According to the previous reusable charts pattern:

// Select the svg element, if it exists.
var svg = d3.select(this).selectAll("svg").data([data]);

// Enter
svg.enter().append("svg").append("g");

// Update
svg.attr("width", width).attr("height", height);

...

Another approach found here

  var div = d3.select(this),
      g = div.select("g");

  // Create the skeletal chart.
  if (g.empty()) {

    // Create svg here

You can quickly test how your chart behaves with random updates:

setInterval(function() {

    d3.select("body")
      .datum(d3.range(Math.floor(Math.random()*100))
                .map(function() { return Math.random(); })
            )
    .call(chart);

}, 1000)

Turn the bar chart into a plugin

ℹ️ Everything in D3 is a plugin, including core features like colors, scales, and selections.

Here is a list of d3 plugins

As a recall, here are example of modules:

We are going to create a D3 chart as a D3 plugin

Below is the suggested code organization which follows our:

d3-foo
├── .gitignore
├── .npmignore
├── LICENSE
├── README.md
├── index.js
├── package.json
├─┬ src
│ └── foo.js
└─┬ test
  └── foo-test.js

Let's compile our module

rollup -f umd -n d3 -o build/d3-barchart.js -- index.js

Update the barchart-module.html code as follows

  var chart = d3.barchart().width(720).height(80);

Not that it might be a good idea to serialize configuration as an object:

  .params({
    width: 500,
    height: 500
  })

Notes

Create more reusable chart!

Next

Go to STEP 03