```javascript
{
- // Create elements for each piece of data in the dataset. Store elements in an array on the dataset as dataset.metaData
- addElements: function() {},
-
- // Draw the representation of the dataset
- draw: function() {},
-
- // Remove hover styling from the given element
- removeHoverStyle: function(element, datasetIndex, index) {},
+ // 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,
+ }
- // Add hover styling to the given element
- setHoverStyle: function(element, datasetIndex, index) {},
+ // ID of the controller
+ id: string;
// Update the elements in response to new data
// @param mode : update mode, core calls this method using any of `'active'`, `'hide'`, `'reset'`, `'resize'`, `'show'` or `undefined`
```javascript
{
+ // 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() {},
+
// Initializes the controller
initialize: function() {},
// chart types using a single scale
linkScales: function() {},
- // Called by the main chart controller when an update is triggered. The default implementation handles the number of data points changing and creating elements appropriately.
- buildOrUpdateElements: function() {}
+ // 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) {},
}
```
import {BubbleController} from 'chart.js';
class Custom extends BubbleController {
draw() {
- // Call super method first
+ // Call bubble controller method to draw all the points
super.draw(arguments);
// Now we can do some custom drawing for this dataset. Here we'll draw a red box around the first point in each dataset
- var meta = this.getMeta();
- var pt0 = meta.data[0];
- var radius = pt0.radius;
+ const meta = this.getMeta();
+ const pt0 = meta.data[0];
+
+ const {x, y} = pt0.getProps(['x', 'y']);
+ const {radius} = pt0.options;
- var ctx = this.chart.chart.ctx;
+ const ctx = this.chart.ctx;
ctx.save();
ctx.strokeStyle = 'red';
ctx.lineWidth = 1;
- ctx.strokeRect(pt0.x - radius, pt0.y - radius, 2 * radius, 2 * radius);
+ ctx.strokeRect(x - radius, y - radius, 2 * radius, 2 * radius);
ctx.restore();
}
});
--- /dev/null
+<!doctype html>
+<html>
+
+<head>
+ <title>Logarithmic Line Chart</title>
+ <script src="../../dist/chart.min.js"></script>
+ <script src="../utils.js"></script>
+ <style>
+ canvas {
+ -moz-user-select: none;
+ -webkit-user-select: none;
+ -ms-user-select: none;
+ }
+ </style>
+</head>
+
+<body>
+ <div style="width:75%;">
+ <canvas id="canvas"></canvas>
+ </div>
+ <script>
+ var randomScalingFactor = function() {
+ return Math.pow(2, Math.ceil(Math.random() * 10));
+ };
+
+ class Log2Axis extends Chart.Scale {
+ constructor(cfg) {
+ super(cfg);
+ this._startValue = undefined;
+ this._valueRange = 0;
+ }
+
+ parse(raw, index) {
+ const value = Chart.registry.getScale('linear').prototype.parse.apply(this, [raw, index]);
+ return isFinite(value) && value > 0 ? value : null;
+ }
+
+ determineDataLimits() {
+ const {min, max} = this.getMinMax(true);
+ this.min = isFinite(min) ? Math.max(0, min) : null;
+ this.max = isFinite(max) ? Math.max(0, max) : null;
+ }
+
+ buildTicks() {
+ const ticks = [];
+
+ let power = Math.floor(Math.log2(this.min));
+ let maxPower = Math.ceil(Math.log2(this.max));
+ while (power <= maxPower) {
+ ticks.push({value: Math.pow(2, power)});
+ power += 1;
+ }
+
+ this.min = ticks[0].value;
+ this.max = ticks[ticks.length - 1].value;
+ return ticks;
+ }
+
+ /**
+ * @protected
+ */
+ configure() {
+ const start = this.min;
+
+ super.configure();
+
+ this._startValue = Math.log2(start);
+ this._valueRange = Math.log2(this.max) - Math.log2(start);
+ }
+
+ getPixelForValue(value) {
+ if (value === undefined || value === 0) {
+ value = this.min;
+ }
+
+ return this.getPixelForDecimal(value === this.min ? 0 : (Math.log2(value) - this._startValue) / this._valueRange);
+ }
+
+ getValueForPixel(pixel) {
+ const decimal = this.getDecimalForPixel(pixel);
+ return Math.pow(2, this._startValue + decimal * this._valueRange);
+ }
+ }
+
+ Log2Axis.id = 'log2';
+ Log2Axis.defaults = {};
+ Chart.register(Log2Axis);
+
+ var config = {
+ type: 'line',
+ data: {
+ labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
+ datasets: [{
+ label: 'My First dataset',
+ backgroundColor: window.chartColors.red,
+ borderColor: window.chartColors.red,
+ fill: false,
+ data: [
+ randomScalingFactor(),
+ randomScalingFactor(),
+ randomScalingFactor(),
+ randomScalingFactor(),
+ randomScalingFactor(),
+ randomScalingFactor(),
+ randomScalingFactor()
+ ],
+ }]
+ },
+ options: {
+ responsive: true,
+ plugins: {
+ title: {
+ display: true,
+ text: 'Derived Axis Type - Log2'
+ }
+ },
+ scales: {
+ x: {
+ display: true,
+ },
+ y: {
+ display: true,
+ type: 'log2',
+ }
+ }
+ }
+ };
+
+ window.onload = function() {
+ var ctx = document.getElementById('canvas').getContext('2d');
+ window.myLine = new Chart(ctx, config);
+ };
+ </script>
+</body>
+
+</html>
--- /dev/null
+<!doctype html>
+<html>
+
+<head>
+ <title>Derived Chart Type</title>
+ <script src="../../dist/chart.min.js"></script>
+ <script src="../utils.js"></script>
+ <style type="text/css">
+ canvas{
+ -moz-user-select: none;
+ -webkit-user-select: none;
+ -ms-user-select: none;
+ }
+ </style>
+</head>
+
+<body>
+ <div id="container" style="width: 75%;">
+ <canvas id="canvas"></canvas>
+ </div>
+ <script>
+ class Custom extends Chart.controllers.bubble {
+ draw() {
+ // Call bubble controller method to draw all the points
+ super.draw(arguments);
+
+ // Now we can do some custom drawing for this dataset. Here we'll draw a red box around the first point in each dataset
+ var meta = this.getMeta();
+ var pt0 = meta.data[0];
+
+ const {x, y} = pt0.getProps(['x', 'y']);
+ const {radius} = pt0.options;
+
+ var ctx = this.chart.ctx;
+ ctx.save();
+ ctx.strokeStyle = 'red';
+ ctx.lineWidth = 1;
+ ctx.strokeRect(x - radius, y - radius, 2 * radius, 2 * radius);
+ ctx.restore();
+ }
+ }
+ Custom.id = 'derivedBubble';
+ Custom.defaults = Chart.controllers.bubble.defaults;
+
+ // Stores the controller so that the chart initialization routine can look it up
+ Chart.register(Custom);
+
+ var color = Chart.helpers.color;
+ var bubbleChartData = {
+ datasets: [{
+ label: 'My First dataset',
+ backgroundColor: color(window.chartColors.blue).alpha(0.5).rgbString(),
+ borderColor: window.chartColors.blue,
+ borderWidth: 1,
+ data: [{
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ r: Math.abs(randomScalingFactor()) / 5,
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ r: Math.abs(randomScalingFactor()) / 5,
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ r: Math.abs(randomScalingFactor()) / 5,
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ r: Math.abs(randomScalingFactor()) / 5,
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ r: Math.abs(randomScalingFactor()) / 5,
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ r: Math.abs(randomScalingFactor()) / 5,
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ r: Math.abs(randomScalingFactor()) / 5,
+ }]
+ }]
+ };
+
+ window.onload = function() {
+ var ctx = document.getElementById('canvas').getContext('2d');
+ window.myChart = new Chart(ctx, {
+ type: 'derivedBubble',
+ data: bubbleChartData,
+ options: {
+ responsive: true,
+ plugins: {
+ title: {
+ display: true,
+ text: 'Derived Chart Type'
+ },
+ }
+ }
+ });
+ };
+ </script>
+</body>
+
+</html>
}, {
title: 'Programmatic Event Triggers',
path: 'advanced/programmatic-events.html'
+ }, {
+ title: 'Derived Chart Type',
+ path: 'advanced/derived-chart-type.html'
+ }, {
+ title: 'Derived Axis Type',
+ path: 'advanced/derived-axis-type.html'
}]
}];