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

Make bar styling options scriptable #5780

Merged
merged 1 commit into from Nov 12, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
80 changes: 59 additions & 21 deletions docs/charts/bar.md
Expand Up @@ -61,31 +61,69 @@ var myBarChart = new Chart(ctx, {
```

## Dataset Properties
The bar 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 the bars is generally set this way.

Some properties can be specified as an array. If these are set to an array value, the first value applies to the first bar, the second value to the second bar, and so on.
The bar 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 color of the bars is generally set this way.

| 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/Color[]` | The fill color of the bar. See [Colors](../general/colors.md#colors).
| `borderColor` | `Color/Color[]` | The color of the bar border. See [Colors](../general/colors.md#colors).
| `borderWidth` | `Number/Number[]` | The stroke width of the bar in pixels.
| `borderSkipped` | `String` | Which edge to skip drawing the border for. [more...](#borderskipped)
| `hoverBackgroundColor` | `Color/Color[]` | The fill colour of the bars when hovered.
| `hoverBorderColor` | `Color/Color[]` | The stroke colour of the bars when hovered.
| `hoverBorderWidth` | `Number/Number[]` | The stroke width of the bars when hovered.

### borderSkipped
This setting is used to avoid drawing the bar stroke at the base of the fill. In general, this does not need to be changed except when creating chart types that derive from a bar chart.
| Name | Type | [Scriptable](../general/options.md#scriptable-options) | [Indexable](../general/options.md#indexable-options) | Default
| ---- | ---- | :----: | :----: | ----
| [`backgroundColor`](#styling) | [`Color`](../general/colors.md) | Yes | Yes | `'rgba(0,0,0,0.1)'`
| [`borderColor`](#styling) | [`Color`](../general/colors.md) | Yes | Yes | `'rgba(0,0,0,0.1)'`
| [`borderSkipped`](#borderskipped) | `String` | Yes | Yes | `'bottom'`
| [`borderWidth`](#styling) | `Number` | Yes | Yes | `0`
| [`data`](#data-structure) | `Object[]` | - | - | **required**
| [`hoverBackgroundColor`](#interactions) | [`Color`](../general/colors.md) | - | - | `undefined`
| [`hoverBorderColor`](#interactions) | [`Color`](../general/colors.md) | - | - | `undefined`
| [`hoverBorderWidth`](#interactions) | `Number` | - | - | `1`
| [`label`](#general) | `String` | - | - | `''`
| [`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.

### Styling

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

| Name | Description
| ---- | ----
| `backgroundColor` | The bar background color.
| `borderColor` | The bar border color.
| [`borderSkipped`](#borderskipped) | The edge to skip when drawing bar.
| `borderWidth` | The bar border width (in pixels).

All these values, if `undefined`, fallback to the associated [`elements.rectangle.*`](../configuration/elements.md#rectangle-configuration) options.

#### borderSkipped

This setting is used to avoid drawing the bar stroke at the base of the fill.
In general, this does not need to be changed except when creating chart types
that derive from a bar chart.

Options are:
* 'bottom'
* 'left'
* 'top'
* 'right'
* `'bottom'`
* `'left'`
* `'top'`
* `'right'`

### Interactions

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

| Name | Description
| ---- | -----------
| `hoverBackgroundColor` | The bar background color when hovered.
| `hoverBorderColor` | The bar border color hovered.
| `hoverBorderWidth` | The bar border width when hovered (in pixels).

All these values, if `undefined`, fallback to the associated [`elements.point.*`](../configuration/elements.md#point-configuration) options.

## Configuration Options

Expand Down
10 changes: 5 additions & 5 deletions gulpfile.js
Expand Up @@ -186,16 +186,16 @@ function lintHtmlTask() {
}

function docsTask(done) {
const script = require.resolve('gitbook-cli/bin/gitbook.js');
const cmd = process.execPath;
var script = require.resolve('gitbook-cli/bin/gitbook.js');
var cmd = '"' + process.execPath + '"';

exec([cmd, script, 'install', './'].join(' ')).then(() => {
return exec([cmd, script, argv.watch ? 'serve' : 'build', './', './dist/docs'].join(' '));
}).catch((err) => {
console.error(err.stdout);
}).then(() => {
done();
});
}).catch((err) => {
done(new Error(err.stdout || err));
})
}

function unittestTask(done) {
Expand Down
3 changes: 3 additions & 0 deletions samples/samples.js
Expand Up @@ -176,6 +176,9 @@
}, {
title: 'Scriptable',
items: [{
title: 'Bar Chart',
path: 'scriptable/bar.html'
}, {
title: 'Bubble Chart',
path: 'scriptable/bubble.html'
}]
Expand Down
95 changes: 95 additions & 0 deletions samples/scriptable/bar.html
@@ -0,0 +1,95 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Scriptable > Bar | Chart.js sample</title>
<link rel="stylesheet" type="text/css" href="../style.css">
<script src="../../dist/Chart.js"></script>
<script src="../utils.js"></script>
</head>
<body>
<div class="content">
<div class="wrapper"><canvas id="chart-0"></canvas></div>
<div class="toolbar">
<button onclick="randomize(this)">Randomize</button>
<button onclick="addDataset(this)">Add Dataset</button>
<button onclick="removeDataset(this)">Remove Dataset</button>
</div>
</div>

<script>
var DATA_COUNT = 16;

var utils = Samples.utils;

utils.srand(110);

function colorize(opaque, ctx) {
var v = ctx.dataset.data[ctx.dataIndex];
var c = v < -50 ? '#D60000'
: v < 0 ? '#F46300'
: v < 50 ? '#0358B6'
: '#44DE28';

return opaque ? c : utils.transparentize(c, 1 - Math.abs(v / 150));
}

function generateData() {
return utils.numbers({
count: DATA_COUNT,
min: -100,
max: 100
});
}

var data = {
labels: utils.months({count: DATA_COUNT}),
datasets: [{
data: generateData()
}]
};

var options = {
legend: false,
tooltips: false,
elements: {
rectangle: {
backgroundColor: colorize.bind(null, false),
borderColor: colorize.bind(null, true),
borderWidth: 2
}
}
};

var chart = new Chart('chart-0', {
type: 'bar',
data: data,
options: options
});

// eslint-disable-next-line no-unused-vars
function randomize() {
chart.data.datasets.forEach(function(dataset) {
dataset.data = generateData();
});
chart.update();
}

// eslint-disable-next-line no-unused-vars
function addDataset() {
chart.data.datasets.push({
data: generateData()
});
chart.update();
}

// eslint-disable-next-line no-unused-vars
function removeDataset() {
chart.data.datasets.shift();
chart.update();
}
</script>
</body>
</html>
4 changes: 2 additions & 2 deletions samples/utils.js
Expand Up @@ -11,7 +11,7 @@ window.chartColors = {
};

(function(global) {
var Months = [
var MONTHS = [
'January',
'February',
'March',
Expand Down Expand Up @@ -106,7 +106,7 @@ window.chartColors = {
var i, value;

for (i = 0; i < count; ++i) {
value = Months[Math.ceil(i) % 12];
value = MONTHS[Math.ceil(i) % 12];
values.push(value.substring(0, section));
}

Expand Down
60 changes: 49 additions & 11 deletions src/controllers/controller.bar.js
Expand Up @@ -213,35 +213,32 @@ module.exports = function(Chart) {

updateElement: function(rectangle, index, reset) {
var me = this;
var chart = me.chart;
var meta = me.getMeta();
var dataset = me.getDataset();
var custom = rectangle.custom || {};
var rectangleOptions = chart.options.elements.rectangle;
var options = me._resolveElementOptions(rectangle, index);

rectangle._xScale = me.getScaleForId(meta.xAxisID);
rectangle._yScale = me.getScaleForId(meta.yAxisID);
rectangle._datasetIndex = me.index;
rectangle._index = index;

rectangle._model = {
backgroundColor: options.backgroundColor,
borderColor: options.borderColor,
borderSkipped: options.borderSkipped,
borderWidth: options.borderWidth,
datasetLabel: dataset.label,
label: chart.data.labels[index],
borderSkipped: custom.borderSkipped ? custom.borderSkipped : rectangleOptions.borderSkipped,
backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.valueAtIndexOrDefault(dataset.backgroundColor, index, rectangleOptions.backgroundColor),
borderColor: custom.borderColor ? custom.borderColor : helpers.valueAtIndexOrDefault(dataset.borderColor, index, rectangleOptions.borderColor),
borderWidth: custom.borderWidth ? custom.borderWidth : helpers.valueAtIndexOrDefault(dataset.borderWidth, index, rectangleOptions.borderWidth)
label: me.chart.data.labels[index]
};

me.updateElementGeometry(rectangle, index, reset);
me._updateElementGeometry(rectangle, index, reset);

rectangle.pivot();
},

/**
* @private
*/
updateElementGeometry: function(rectangle, index, reset) {
_updateElementGeometry: function(rectangle, index, reset) {
var me = this;
var model = rectangle._model;
var vscale = me.getValueScale();
Expand Down Expand Up @@ -472,6 +469,47 @@ module.exports = function(Chart) {

helpers.canvas.unclipArea(chart.ctx);
},

/**
* @private
*/
_resolveElementOptions: function(rectangle, index) {
var me = this;
var chart = me.chart;
var datasets = chart.data.datasets;
var dataset = datasets[me.index];
var custom = rectangle.custom || {};
var options = chart.options.elements.rectangle;
var resolve = helpers.options.resolve;
simonbrunel marked this conversation as resolved.
Show resolved Hide resolved
var values = {};
var i, ilen, key;

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

var keys = [
'backgroundColor',
'borderColor',
'borderSkipped',
'borderWidth'
];

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

return values;
}
});

Chart.controllers.horizontalBar = Chart.controllers.bar.extend({
Expand Down
3 changes: 3 additions & 0 deletions src/controllers/controller.bubble.js
Expand Up @@ -103,12 +103,14 @@ module.exports = function(Chart) {
setHoverStyle: function(point) {
var model = point._model;
var options = point._options;

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

model.backgroundColor = helpers.valueOrDefault(options.hoverBackgroundColor, helpers.getHoverColor(options.backgroundColor));
model.borderColor = helpers.valueOrDefault(options.hoverBorderColor, helpers.getHoverColor(options.borderColor));
model.borderWidth = helpers.valueOrDefault(options.hoverBorderWidth, options.borderWidth);
Expand Down Expand Up @@ -167,6 +169,7 @@ module.exports = function(Chart) {
dataset.radius,
options.radius
], context, index);

return values;
}
});
Expand Down