New Charts

Chart.js 2.0 introduced the concept of controllers for each dataset. Like scales, new controllers can be written as needed.

  1. class MyType extends Chart.DatasetController {
  2. }
  3. Chart.register(MyType);
  4. // Now we can create a new instance of our chart, using the Chart.js API
  5. new Chart(ctx, {
  6. // this is the string the constructor was registered at, ie Chart.controllers.MyType
  7. type: 'MyType',
  8. data: data,
  9. options: options
  10. });

Dataset Controller Interface

Dataset controllers must implement the following interface.

  1. {
  2. // Defaults for charts of this type
  3. defaults: {
  4. // If set to `false` or `null`, no dataset level element is created.
  5. // If set to a string, this is the type of element to create for the dataset.
  6. // For example, a line create needs to create a line element so this is the string 'line'
  7. datasetElementType: string | null | false,
  8. // If set to `false` or `null`, no elements are created for each data value.
  9. // If set to a string, this is the type of element to create for each data value.
  10. // For example, a line create needs to create a point element so this is the string 'point'
  11. dataElementType: string | null | false,
  12. }
  13. // ID of the controller
  14. id: string;
  15. // Update the elements in response to new data
  16. // @param mode : update mode, core calls this method using any of `'active'`, `'hide'`, `'reset'`, `'resize'`, `'show'` or `undefined`
  17. update: function(mode) {}
  18. }

The following methods may optionally be overridden by derived dataset controllers.

  1. {
  2. // Draw the representation of the dataset. The base implementation works in most cases, and an example of a derived version
  3. // can be found in the line controller
  4. draw: function() {},
  5. // Initializes the controller
  6. initialize: function() {},
  7. // Ensures that the dataset represented by this controller is linked to a scale. Overridden to helpers.noop in the polar area and doughnut controllers as these
  8. // chart types using a single scale
  9. linkScales: function() {},
  10. // Parse the data into the controller meta data. The default implementation will work for cartesian parsing, but an example of an overridden
  11. // version can be found in the doughnut controller
  12. parse: function(start, count) {},
  13. }

Extending Existing Chart Types

Extending or replacing an existing controller type is easy. Simply replace the constructor for one of the built in types with your own.

The built in controller types are:

  • BarController
  • BubbleController
  • DoughnutController
  • LineController
  • PieController
  • PolarAreaController
  • RadarController
  • ScatterController

These controllers are also available in the UMD package, directly under Chart. Eg: Chart.BarController.

For example, to derive a new chart type that extends from a bubble chart, you would do the following.

  1. import {BubbleController} from 'chart.js';
  2. class Custom extends BubbleController {
  3. draw() {
  4. // Call bubble controller method to draw all the points
  5. super.draw(arguments);
  6. // Now we can do some custom drawing for this dataset. Here we'll draw a red box around the first point in each dataset
  7. const meta = this.getMeta();
  8. const pt0 = meta.data[0];
  9. const {x, y} = pt0.getProps(['x', 'y']);
  10. const {radius} = pt0.options;
  11. const ctx = this.chart.ctx;
  12. ctx.save();
  13. ctx.strokeStyle = 'red';
  14. ctx.lineWidth = 1;
  15. ctx.strokeRect(x - radius, y - radius, 2 * radius, 2 * radius);
  16. ctx.restore();
  17. }
  18. };
  19. Custom.id = 'derivedBubble';
  20. Custom.defaults = BubbleController.defaults;
  21. // Stores the controller so that the chart initialization routine can look it up
  22. Chart.register(Custom);
  23. // Now we can create and use our new chart type
  24. new Chart(ctx, {
  25. type: 'derivedBubble',
  26. data: data,
  27. options: options
  28. });

TypeScript Typings

If you want your new chart type to be statically typed, you must provide a .d.ts TypeScript declaration file. Chart.js provides a way to augment built-in types with user-defined ones, by using the concept of “declaration merging”.

When adding a new chart type, ChartTypeRegistry must contains the declarations for the new type, either by extending an existing entry in ChartTypeRegistry or by creating a new one.

For example, to provide typings for a new chart type that extends from a bubble chart, you would add a .d.ts containing:

  1. import { ChartTypeRegistry } from 'chart.js'
  2. declare module 'chart.js' {
  3. interface ChartTypeRegistry {
  4. derivedBubble: ChartTypeRegistry['bubble']
  5. }
  6. }