Skip to content
Jon Adams edited this page Feb 21, 2014 · 6 revisions

Chart: Create

There are two ways to define a new chart type:

  1. From scratch
  2. As an extension of another chart

Defining a new chart

You can create a new chart constructor by calling the d3.chart function as follows. You can then instatiate that chart one or more times by calling chart on any d3 selection.

d3.chart("ChartType", {
  initialize: function() {}  
});

var myChart = d3.select("#container")
  .append("div#vis")
  .chart("ChartType");

myChart.draw([1,2,3,4,5]);

Note that the chart type name is capitalized. While this is not enforced, we highly recommend this convention because we are effectively creating a "constructor" for a chart and thus following the traditional JavaScript practice of capitalizing our constructor names.

Adding configuration functions

Any properties & methods you define as part of the second object argument to of d3.chart will be available on any chart instance you create. For example:

d3.chart("ChartType", {
  width: function(newWidth) {
    if (arguments.length === 0) {
      return this.w;
    }
    this.w = newWidth;
    return this;
  }  
});

var myChart = d3.select("#container").append("svg")
  .chart("ChartType")
  .width(110);

var anotherChart = d3.select("#container").append("svg")
  .chart("ChartType")
  .width(210);

Note the getter/setter pattern we're using - it allows us to call width() without arguments to get the current width, or to set a new width by calling width(someValue).

Extending an existing chart

If a chart already exists and you wish to define a chart that inherits the first chart's behavior but extends/enhances it in some way, you can use the extend method to define a new chart type that is based of the chart you're extending. For example, given the ChartType defined above:

d3.chart("ChartType").extend("FancyChartType", {
  fancy: function(isFancy) {
    if (arguments.length === 0) {
      return this.f;
    }
    this.f = isFancy;
    return this;
  }  
});

var myChart = d3.select("#container")
  .append("svg")
  .chart("FancyChartType")
  .fancy(true)
  .width(110);

Note that our FancyChartType still has access to all the methods defined in ChartType. The initialize method we'd define in our first chart type will be called first, followed by the one of our extended chart and so on when we create an instance.