Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Line scriptable options #5973

Merged
merged 14 commits into from Jan 15, 2019
Merged
115 changes: 84 additions & 31 deletions docs/charts/line.md
Expand Up @@ -41,37 +41,90 @@ var myLineChart = new Chart(ctx, {

The line chart allows a number of properties to be specified for each dataset. These are used to set display properties for a specific dataset. For example, the colour of a line is generally set this way.

All point* properties can be specified as an array. If these are set to an array value, the first value applies to the first point, the second value to the second point, and so on.

| Name | Type | Description
| ---- | ---- | -----------
| `label` | `String` | The label for the dataset which appears in the legend and tooltips.
| `xAxisID` | `String` | The ID of the x axis to plot this dataset on. If not specified, this defaults to the ID of the first found x axis.
| `yAxisID` | `String` | The ID of the y axis to plot this dataset on. If not specified, this defaults to the ID of the first found y axis.
| `backgroundColor` | `Color` | The fill color under the line. See [Colors](../general/colors.md#colors).
| `borderColor` | `Color` | The color of the line. See [Colors](../general/colors.md#colors).
| `borderWidth` | `Number` | The width of the line in pixels.
| `borderDash` | `Number[]` | Length and spacing of dashes. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash).
| `borderDashOffset` | `Number` | Offset for line dashes. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineDashOffset).
| `borderCapStyle` | `String` | Cap style of the line. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineCap).
| `borderJoinStyle` | `String` | Line joint style. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineJoin).
| `cubicInterpolationMode` | `String` | Algorithm used to interpolate a smooth curve from the discrete data points. [more...](#cubicinterpolationmode)
| `fill` | `Boolean/String` | How to fill the area under the line. See [area charts](area.md).
| `lineTension` | `Number` | Bezier curve tension of the line. Set to 0 to draw straightlines. This option is ignored if monotone cubic interpolation is used.
| `pointBackgroundColor` | `Color/Color[]` | The fill color for points.
| `pointBorderColor` | `Color/Color[]` | The border color for points.
| `pointBorderWidth` | `Number/Number[]` | The width of the point border in pixels.
| `pointRadius` | `Number/Number[]` | The radius of the point shape. If set to 0, the point is not rendered.
| `pointStyle` | `String/String[]/Image/Image[]` | Style of the point. [more...](../configuration/elements#point-styles)
| `pointRotation` | `Number/Number[]` | The rotation of the point in degrees.
| `pointHitRadius` | `Number/Number[]` | The pixel size of the non-displayed point that reacts to mouse events.
| `pointHoverBackgroundColor` | `Color/Color[]` | Point background color when hovered.
| `pointHoverBorderColor` | `Color/Color[]` | Point border color when hovered.
| `pointHoverBorderWidth` | `Number/Number[]` | Border width of point when hovered.
| `pointHoverRadius` | `Number/Number[]` | The radius of the point when hovered.
| `showLine` | `Boolean` | If false, the line is not drawn for this dataset.
| `spanGaps` | `Boolean` | If true, lines will be drawn between points with no or null data. If false, points with `NaN` data will create a break in the line.
| `steppedLine` | `Boolean/String` | If the line is shown as a stepped line. [more...](#stepped-line)
| Name | Type | [Scriptable](../general/options.md#scriptable-options) | [Indexable](../general/options.md#indexable-options) | Default
benmccann marked this conversation as resolved.
Show resolved Hide resolved
| ---- | ---- | :----: | :----: | ----
| [`backgroundColor`](#line-styling) | [`Color`](../general/colors.md) | - | - | `'rgba(0,0,0,0.1)'`
| [`borderCapStyle`](#line-styling) | `String` | - | - | `'butt'`
| [`borderColor`](#line-styling) | [`Color`](../general/colors.md) | - | - | `'rgba(0,0,0,0.1)'`
| [`borderDash`](#line-styling) | `Number[]` | - | - | `[]`
| [`borderDashOffset`](#line-styling) | `Number` | - | - | `0`
| [`borderJoinStyle`](#line-styling) | `String` | - | - | `'miter'`
| [`borderWidth`](#line-styling) | `Number` | - | - | `0`
| [`cubicInterpolationMode`](#cubicInterpolationMode) | `String` | - | - | `''`
| [`fill`](#line-styling) | `Boolean/String` | - | - | `true`
| [`label`](#general) | `String` | - | - | `''`
| [`lineTension`](#line-styling) | `Number` | - | - | `0.4`
| [`pointBackgroundColor`](#point-styling) | `Color` | Yes | Yes | `'rgba(0,0,0,0.1)'`
| [`pointBorderColor`](#point-styling) | `Color` | Yes | Yes | `'rgba(0,0,0,0.1)'`
| [`pointBorderWidth`](#point-styling) | `Number` | Yes | Yes | `1`
| [`pointHitRadius`](#point-styling) | `Number` | Yes | Yes | `1`
| [`pointHoverBackgroundColor`](#interactions) | `Color` | Yes | Yes | `undefined`
| [`pointHoverBorderColor`](#interactions) | `Color` | Yes | Yes | `undefined`
| [`pointHoverBorderWidth`](#interactions) | `Number` | Yes | Yes | `undefined`
| [`pointHoverRadius`](#interactions) | `Number` | Yes | Yes | `undefined`
| [`pointRadius`](#point-styling) | `Number` | Yes | Yes | `3`
| [`pointRotation`](#point-styling) | `Number` | Yes | Yes | `1`
| [`pointStyle`](#point-styling) | `String/Image` | Yes | Yes | `'circle'`
| [`showLine`](#general) | `Boolean` | - | - | `undefined`
| [`spanGaps`](#general) | `Boolean` | - | - | `false`
| [`steppedLine`](#stepped-line) | `Boolean/String` | - | - | `false`
| [`xAxisID`](#general) | `String` | - | - | first x axis
| [`yAxisID`](#general) | `String` | - | - | first y axis

### General

| Name | Description
| ---- | ----
| `label` | The label for the dataset which appears in the legend and tooltips.
| `xAxisID` | The ID of the x axis to plot this dataset on.
| `yAxisID` | The ID of the y axis to plot this dataset on.

### Point Styling

The style of each point can be controlled with the following properties:

| Name | Description
| ---- | ----
| `pointBackgroundColor` | The fill color for points.
| `pointBorderColor` | The border color for points.
| `pointBorderWidth` | The width of the point border in pixels.
| `pointHitRadius` | The pixel size of the non-displayed point that reacts to mouse events.
| `pointRadius` | The radius of the point shape. If set to 0, the point is not rendered.
| `pointRotation` | The rotation of the point in degrees.
| `pointStyle` | Style of the point. [more...](../configuration/elements#point-styles)

etimberg marked this conversation as resolved.
Show resolved Hide resolved
All these values, if `undefined`, fallback first to the dataset options then to the associated [`elements.point.*`](../configuration/elements.md#point-configuration) options.

### Line Styling

The style of the line can be controlled with the following properties:

| Name | Description
| ---- | ----
| `backgroundColor` | The line fill color.
| `borderCapStyle` | Cap style of the line. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineCap).
| `borderColor` | The line color.
| `borderDash` | Length and spacing of dashes. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash).
| `borderDashOffset` | Offset for line dashes. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineDashOffset).
| `borderJoinStyle` | Line joint style. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineJoin).
| `borderWidth` | The line width (in pixels).
| `fill` | How to fill the area under the line. See [area charts](area.md).
| `lineTension` | Bezier curve tension of the line. Set to 0 to draw straightlines. This option is ignored if monotone cubic interpolation is used.
| `showLine` | If false, the line is not drawn for this dataset.
| `spanGaps` | If true, lines will be drawn between points with no or null data. If false, points with `NaN` data will create a break in the line.

etimberg marked this conversation as resolved.
Show resolved Hide resolved
All these values, if `undefined`, fallback to the associated [`elements.line.*`](../configuration/elements.md#line-configuration) options.

### Interactions

The interaction with each point can be controlled with the following properties:

| Name | Description
| ---- | -----------
| `pointHoverBackgroundColor` | Point background color when hovered.
| `pointHoverBorderColor` | Point border color when hovered.
| `pointHoverBorderWidth` | Border width of point when hovered.
| `pointHoverRadius` | The radius of the point when hovered.

### cubicInterpolationMode
The following interpolation modes are supported.
Expand Down
2 changes: 1 addition & 1 deletion docs/general/options.md
Expand Up @@ -2,7 +2,7 @@

## Scriptable Options

Scriptable options also accept a function which is called for each data and that takes the unique argument `context` representing contextual information (see [option context](options.md#option-context)).
Scriptable options also accept a function which is called for each of the underlying data values and that takes the unique argument `context` representing contextual information (see [option context](options.md#option-context)).

Example:

Expand Down
143 changes: 70 additions & 73 deletions src/controllers/controller.line.js
Expand Up @@ -103,52 +103,6 @@ module.exports = DatasetController.extend({
}
},

getPointBackgroundColor: function(point, index) {
var dataset = this.getDataset();
var custom = point.custom || {};

return resolve([
custom.backgroundColor,
dataset.pointBackgroundColor,
dataset.backgroundColor,
this.chart.options.elements.point.backgroundColor
], undefined, index);
},

getPointBorderColor: function(point, index) {
var dataset = this.getDataset();
var custom = point.custom || {};

return resolve([
custom.borderColor,
dataset.pointBorderColor,
dataset.borderColor,
this.chart.options.elements.point.borderColor
], undefined, index);
},

getPointBorderWidth: function(point, index) {
var dataset = this.getDataset();
var custom = point.custom || {};

return resolve([
custom.borderWidth,
dataset.pointBorderWidth,
dataset.borderWidth,
this.chart.options.elements.point.borderWidth
], undefined, index);
},

getPointRotation: function(point, index) {
var custom = point.custom || {};

return resolve([
custom.rotation,
this.getDataset().pointRotation,
this.chart.options.elements.point.rotation
], undefined, index);
},

updateElement: function(point, index, reset) {
var me = this;
var meta = me.getMeta();
Expand All @@ -158,23 +112,17 @@ module.exports = DatasetController.extend({
var value = dataset.data[index];
var yScale = me.getScaleForId(meta.yAxisID);
var xScale = me.getScaleForId(meta.xAxisID);
var pointOptions = me.chart.options.elements.point;
var x, y;

// Compatibility: If the properties are defined with only the old name, use those values
if ((dataset.radius !== undefined) && (dataset.pointRadius === undefined)) {
dataset.pointRadius = dataset.radius;
}
if ((dataset.hitRadius !== undefined) && (dataset.pointHitRadius === undefined)) {
dataset.pointHitRadius = dataset.hitRadius;
}
var options = me._resolveElementOptions(point, index);

x = xScale.getPixelForValue(typeof value === 'object' ? value : NaN, index, datasetIndex);
y = reset ? yScale.getBasePixel() : me.calculatePointY(value, index, datasetIndex);

// Utility
point._xScale = xScale;
point._yScale = yScale;
point._options = options;
point._datasetIndex = datasetIndex;
point._index = index;

Expand All @@ -184,19 +132,68 @@ module.exports = DatasetController.extend({
y: y,
skip: custom.skip || isNaN(x) || isNaN(y),
// Appearance
radius: resolve([custom.radius, dataset.pointRadius, pointOptions.radius], undefined, index),
pointStyle: resolve([custom.pointStyle, dataset.pointStyle, pointOptions.pointStyle], undefined, index),
rotation: me.getPointRotation(point, index),
backgroundColor: me.getPointBackgroundColor(point, index),
borderColor: me.getPointBorderColor(point, index),
borderWidth: me.getPointBorderWidth(point, index),
radius: options.radius,
pointStyle: options.pointStyle,
rotation: options.rotation,
backgroundColor: options.backgroundColor,
borderColor: options.borderColor,
borderWidth: options.borderWidth,
tension: meta.dataset._model ? meta.dataset._model.tension : 0,
steppedLine: meta.dataset._model ? meta.dataset._model.steppedLine : false,
// Tooltip
hitRadius: resolve([custom.hitRadius, dataset.pointHitRadius, pointOptions.hitRadius], undefined, index)
hitRadius: options.hitRadius,
};
},

/**
* @private
*/
_resolveElementOptions: function(point, index) {
var me = this;
var chart = me.chart;
var datasets = chart.data.datasets;
var dataset = datasets[me.index];
var custom = point.custom || {};
var options = chart.options.elements.point;
var values = {};
var i, ilen, key;

// Scriptable options
var context = {
chart: chart,
dataIndex: index,
dataset: dataset,
datasetIndex: me.index
};

var ELEMENT_OPTIONS = {
kurkle marked this conversation as resolved.
Show resolved Hide resolved
backgroundColor: 'pointBackgroundColor',
borderColor: 'pointBorderColor',
borderWidth: 'pointBorderWidth',
hitRadius: 'pointHitRadius',
hoverBackgroundColor: 'pointHoverBackgroundColor',
hoverBorderColor: 'pointHoverBorderColor',
hoverBorderWidth: 'pointHoverBorderWidth',
hoverRadius: 'pointHoverRadius',
pointStyle: 'pointStyle',
radius: 'pointRadius',
rotation: 'pointRotation',
};
var keys = Object.keys(ELEMENT_OPTIONS);

for (i = 0, ilen = keys.length; i < ilen; ++i) {
key = keys[i];
values[key] = resolve([
custom[key],
dataset[ELEMENT_OPTIONS[key]],
dataset[key],
options[key]
], context, index);
}

return values;
},

calculatePointY: function(value, index, datasetIndex) {
var me = this;
var chart = me.chart;
Expand Down Expand Up @@ -317,24 +314,24 @@ module.exports = DatasetController.extend({
}
},

setHoverStyle: function(element) {
// Point
var dataset = this.chart.data.datasets[element._datasetIndex];
var index = element._index;
var custom = element.custom || {};
var model = element._model;
/**
* @protected
*/
setHoverStyle: function(point) {
var model = point._model;
var options = point._options;
var getHoverColor = helpers.getHoverColor;

element.$previousStyle = {
point.$previousStyle = {
backgroundColor: model.backgroundColor,
borderColor: model.borderColor,
borderWidth: model.borderWidth,
radius: model.radius
};

model.backgroundColor = resolve([custom.hoverBackgroundColor, dataset.pointHoverBackgroundColor, getHoverColor(model.backgroundColor)], undefined, index);
model.borderColor = resolve([custom.hoverBorderColor, dataset.pointHoverBorderColor, getHoverColor(model.borderColor)], undefined, index);
model.borderWidth = resolve([custom.hoverBorderWidth, dataset.pointHoverBorderWidth, model.borderWidth], undefined, index);
model.radius = resolve([custom.hoverRadius, dataset.pointHoverRadius, this.chart.options.elements.point.hoverRadius], undefined, index);
}
model.backgroundColor = valueOrDefault(options.hoverBackgroundColor, getHoverColor(options.backgroundColor));
model.borderColor = valueOrDefault(options.hoverBorderColor, getHoverColor(options.borderColor));
model.borderWidth = valueOrDefault(options.hoverBorderWidth, options.borderWidth);
model.radius = valueOrDefault(options.hoverRadius, options.radius);
},
});
56 changes: 56 additions & 0 deletions test/fixtures/controller.line/backgroundColor/indexable.js
@@ -0,0 +1,56 @@
module.exports = {
config: {
type: 'line',
data: {
labels: [0, 1, 2, 3, 4, 5],
datasets: [
{
// option in dataset
data: [0, 5, 10, null, -10, -5],
pointBackgroundColor: [
'#ff0000',
'#00ff00',
'#0000ff',
'#ffff00',
'#ff00ff',
'#000000'
]
},
{
// option in element (fallback)
data: [4, -5, -10, null, 10, 5],
}
]
},
options: {
legend: false,
title: false,
elements: {
line: {
fill: false,
},
point: {
backgroundColor: [
'#ff88ff',
'#888888',
'#ff8800',
'#00ff88',
'#8800ff',
'#ffff88'
],
radius: 10
}
},
scales: {
xAxes: [{display: false}],
yAxes: [{display: false}]
}
}
},
options: {
canvas: {
height: 256,
width: 512
}
}
};
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.