Update chart extension docs + add samples (#8540)

* Update docs on chart extensions
* Working sample for derived chart types
* Add derived axis example
* Remove duplicated line
This commit is contained in:
Evert Timberg 2021-02-28 16:02:44 -05:00 committed by GitHub
parent b795151554
commit c5dcf5a20d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 276 additions and 17 deletions

View File

@ -26,17 +26,21 @@ Dataset controllers must implement the following interface.
```javascript
{
// Create elements for each piece of data in the dataset. Store elements in an array on the dataset as dataset.metaData
addElements: function() {},
// 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,
// Draw the representation of the dataset
draw: function() {},
// 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,
}
// Remove hover styling from the given element
removeHoverStyle: function(element, datasetIndex, index) {},
// 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`
@ -48,6 +52,10 @@ The following methods may optionally be overridden by derived dataset controller
```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() {},
@ -55,8 +63,9 @@ The following methods may optionally be overridden by derived dataset controller
// 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) {},
}
```
@ -83,19 +92,21 @@ For example, to derive a new chart type that extends from a bubble chart, you wo
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];
var ctx = this.chart.chart.ctx;
const {x, y} = pt0.getProps(['x', 'y']);
const {radius} = pt0.options;
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();
}
});

View File

@ -0,0 +1,136 @@
<!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>

View File

@ -0,0 +1,106 @@
<!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>

View File

@ -268,6 +268,12 @@
}, {
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'
}]
}];