2021-03-30 16:32:39 +02:00
# New Charts
2017-03-21 01:36:54 +01:00
2020-08-03 18:33:41 +02:00
Chart.js 2.0 introduced the concept of controllers for each dataset. Like scales, new controllers can be written as needed.
2017-03-21 01:36:54 +01:00
```javascript
2020-05-27 01:16:23 +02:00
class MyType extends Chart.DatasetController {
2017-03-21 01:36:54 +01:00
2020-05-27 01:16:23 +02:00
}
2017-03-21 01:36:54 +01:00
2020-08-03 18:33:41 +02:00
Chart.register(MyType);
2017-03-21 01:36:54 +01:00
// Now we can create a new instance of our chart, using the Chart.js API
new Chart(ctx, {
// this is the string the constructor was registered at, ie Chart.controllers.MyType
type: 'MyType',
data: data,
options: options
});
```
## Dataset Controller Interface
Dataset controllers must implement the following interface.
```javascript
{
2021-02-28 22:02:44 +01:00
// Defaults for charts of this type
defaults: {
// If set to `false` or `null` , no dataset level element is created.
// If set to a string, this is the type of element to create for the dataset.
// For example, a line create needs to create a line element so this is the string 'line'
datasetElementType: string | null | false,
// If set to `false` or `null` , no elements are created for each data value.
// If set to a string, this is the type of element to create for each data value.
// For example, a line create needs to create a point element so this is the string 'point'
dataElementType: string | null | false,
}
2017-03-21 01:36:54 +01:00
2021-02-28 22:02:44 +01:00
// ID of the controller
id: string;
2017-03-21 01:36:54 +01:00
// Update the elements in response to new data
2020-07-13 00:28:39 +02:00
// @param mode : update mode, core calls this method using any of `'active'` , `'hide'` , `'reset'` , `'resize'` , `'show'` or `undefined`
update: function(mode) {}
2017-03-21 01:36:54 +01:00
}
```
2018-11-02 08:46:06 +01:00
The following methods may optionally be overridden by derived dataset controllers.
2020-07-06 23:38:04 +02:00
2017-03-21 01:36:54 +01:00
```javascript
{
2021-02-28 22:02:44 +01:00
// Draw the representation of the dataset. The base implementation works in most cases, and an example of a derived version
// can be found in the line controller
draw: function() {},
2017-03-21 01:36:54 +01:00
// Initializes the controller
2020-07-13 00:28:39 +02:00
initialize: function() {},
2017-03-21 01:36:54 +01:00
// 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
// chart types using a single scale
linkScales: function() {},
2021-02-28 22:02:44 +01:00
// Parse the data into the controller meta data. The default implementation will work for cartesian parsing, but an example of an overridden
// version can be found in the doughnut controller
parse: function(start, count) {},
2017-03-21 01:36:54 +01:00
}
```
## Extending Existing Chart Types
2023-06-05 09:56:56 +02:00
Extending or replacing an existing controller type is easy. Simply replace the constructor for one of the built-in types with your own.
2017-03-21 01:36:54 +01:00
2023-06-05 09:56:56 +02:00
The built-in controller types are:
2020-05-27 01:16:23 +02:00
2020-08-03 18:33:41 +02:00
* `BarController`
* `BubbleController`
* `DoughnutController`
* `LineController`
* `PieController`
* `PolarAreaController`
* `RadarController`
* `ScatterController`
These controllers are also available in the UMD package, directly under `Chart` . Eg: `Chart.BarController` .
2017-03-21 01:36:54 +01:00
For example, to derive a new chart type that extends from a bubble chart, you would do the following.
```javascript
2020-08-03 18:33:41 +02:00
import {BubbleController} from 'chart.js';
class Custom extends BubbleController {
2020-05-27 01:16:23 +02:00
draw() {
2021-02-28 22:02:44 +01:00
// Call bubble controller method to draw all the points
2020-05-27 01:16:23 +02:00
super.draw(arguments);
2017-03-21 01:36:54 +01:00
// Now we can do some custom drawing for this dataset. Here we'll draw a red box around the first point in each dataset
2021-02-28 22:02:44 +01:00
const meta = this.getMeta();
const pt0 = meta.data[0];
const {x, y} = pt0.getProps(['x', 'y']);
const {radius} = pt0.options;
2017-03-21 01:36:54 +01:00
2021-02-28 22:02:44 +01:00
const ctx = this.chart.ctx;
2017-03-21 01:36:54 +01:00
ctx.save();
ctx.strokeStyle = 'red';
ctx.lineWidth = 1;
2021-02-28 22:02:44 +01:00
ctx.strokeRect(x - radius, y - radius, 2 * radius, 2 * radius);
2017-03-21 01:36:54 +01:00
ctx.restore();
}
2021-07-26 15:35:03 +02:00
};
2020-07-06 23:38:04 +02:00
Custom.id = 'derivedBubble';
2020-08-03 18:33:41 +02:00
Custom.defaults = BubbleController.defaults;
2017-03-21 01:36:54 +01:00
2020-07-06 23:38:04 +02:00
// Stores the controller so that the chart initialization routine can look it up
Chart.register(Custom);
2017-03-21 01:36:54 +01:00
// Now we can create and use our new chart type
new Chart(ctx, {
type: 'derivedBubble',
data: data,
2019-01-29 13:34:16 +01:00
options: options
2017-03-21 01:36:54 +01:00
});
```
2020-07-12 00:08:45 +02:00
2020-09-12 02:18:21 +02:00
## 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".
2022-08-22 20:20:35 +02:00
When adding a new chart type, `ChartTypeRegistry` must contain the declarations for the new type, either by extending an existing entry in `ChartTypeRegistry` or by creating a new one.
2020-09-12 02:18:21 +02:00
For example, to provide typings for a new chart type that extends from a bubble chart, you would add a `.d.ts` containing:
2022-08-22 17:58:57 +02:00
```typescript
import { ChartTypeRegistry } from 'chart.js';
2020-09-12 02:18:21 +02:00
declare module 'chart.js' {
2020-11-07 14:35:19 +01:00
interface ChartTypeRegistry {
derivedBubble: ChartTypeRegistry['bubble']
2020-09-12 02:18:21 +02:00
}
}
```