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

Implement dataset.order #6268

Merged
merged 6 commits into from Oct 22, 2019
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
2 changes: 2 additions & 0 deletions docs/charts/bar.md
Expand Up @@ -77,6 +77,7 @@ the color of the bars is generally set this way.
| [`hoverBorderColor`](#interactions) | [`Color`](../general/colors.md) | - | Yes | `undefined`
| [`hoverBorderWidth`](#interactions) | `number` | - | Yes | `1`
| [`label`](#general) | `string` | - | - | `''`
| [`order`](#general) | `number` | - | - | `0`
| [`xAxisID`](#general) | `string` | - | - | first x axis
| [`yAxisID`](#general) | `string` | - | - | first y axis

Expand All @@ -85,6 +86,7 @@ the color of the bars is generally set this way.
| Name | Description
| ---- | ----
| `label` | The label for the dataset which appears in the legend and tooltips.
| `order` | The drawing order of dataset. Also affects order for stacking, tooltip, and legend.
| `xAxisID` | The ID of the x axis to plot this dataset on.
| `yAxisID` | The ID of the y axis to plot this dataset on.

Expand Down
10 changes: 7 additions & 3 deletions docs/charts/bubble.md
Expand Up @@ -49,14 +49,18 @@ The bubble chart allows a number of properties to be specified for each dataset.
| [`hoverBorderWidth`](#interactions) | `number` | Yes | Yes | `1`
| [`hoverRadius`](#interactions) | `number` | Yes | Yes | `4`
| [`hitRadius`](#interactions) | `number` | Yes | Yes | `1`
| [`label`](#labeling) | `string` | - | - | `undefined`
| [`label`](#general) | `string` | - | - | `undefined`
| [`order`](#general) | `number` | - | - | `0`
| [`pointStyle`](#styling) | `string` | Yes | Yes | `'circle'`
| [`rotation`](#styling) | `number` | Yes | Yes | `0`
| [`radius`](#styling) | `number` | Yes | Yes | `3`

### Labeling
### General

`label` defines the text associated to the dataset and which appears in the legend and tooltips.
| Name | Description
| ---- | ----
| `label` | The label for the dataset which appears in the legend and tooltips.
| `order` | The drawing order of dataset.

### Styling

Expand Down
2 changes: 2 additions & 0 deletions docs/charts/line.md
Expand Up @@ -54,6 +54,7 @@ The line chart allows a number of properties to be specified for each dataset. T
| [`fill`](#line-styling) | <code>boolean&#124;string</code> | Yes | - | `true`
| [`label`](#general) | `string` | - | - | `''`
| [`lineTension`](#line-styling) | `number` | - | - | `0.4`
| [`order`](#general) | `number` | - | - | `0`
| [`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`
Expand All @@ -76,6 +77,7 @@ The line chart allows a number of properties to be specified for each dataset. T
| Name | Description
| ---- | ----
| `label` | The label for the dataset which appears in the legend and tooltips.
| `order` | The drawing order of dataset. Also affects order for stacking, tooltip, and legend.
| `xAxisID` | The ID of the x axis to plot this dataset on.
| `yAxisID` | The ID of the y axis to plot this dataset on.

Expand Down
26 changes: 26 additions & 0 deletions docs/charts/mixed.md
Expand Up @@ -70,3 +70,29 @@ At this point we have a chart rendering how we'd like. It's important to note th
}
}
{% endchartjs %}

## Drawing order

By default, datasets are drawn so that first one is top-most. This can be altered by specifying `order` option to datasets. `order` defaults to `0`.

```javascript
var mixedChart = new Chart(ctx, {
type: 'bar',
data: {
datasets: [{
label: 'Bar Dataset',
data: [10, 20, 30, 40],
// this dataset is drawn below
order: 1
}, {
label: 'Line Dataset',
data: [10, 10, 10, 10],
type: 'line',
// this dataset is drawn on top
order: 2
}],
labels: ['January', 'February', 'March', 'April']
},
options: options
});
```
1 change: 1 addition & 0 deletions docs/charts/polar.md
Expand Up @@ -70,6 +70,7 @@ All these values, if `undefined`, fallback to the associated [`elements.arc.*`](
### Border Alignment

The following values are supported for `borderAlign`.

* `'center'` (default)
* `'inner'`

Expand Down
3 changes: 3 additions & 0 deletions docs/charts/radar.md
Expand Up @@ -52,6 +52,7 @@ They are often useful for comparing the points of two or more different data set
{% endchartjs %}

## Example Usage

```javascript
var myRadarChart = new Chart(ctx, {
type: 'radar',
Expand All @@ -75,6 +76,7 @@ The radar chart allows a number of properties to be specified for each dataset.
| [`borderWidth`](#line-styling) | `number` | Yes | - | `3`
| [`fill`](#line-styling) | <code>boolean&#124;string</code> | Yes | - | `true`
| [`label`](#general) | `string` | - | - | `''`
| [`order`](#general) | `number` | - | - | `0`
| [`lineTension`](#line-styling) | `number` | - | - | `0`
| [`pointBackgroundColor`](#point-styling) | `Color` | Yes | Yes | `'rgba(0, 0, 0, 0.1)'`
| [`pointBorderColor`](#point-styling) | `Color` | Yes | Yes | `'rgba(0, 0, 0, 0.1)'`
Expand All @@ -94,6 +96,7 @@ The radar chart allows a number of properties to be specified for each dataset.
| Name | Description
| ---- | ----
| `label` | The label for the dataset which appears in the legend and tooltips.
| `order` | The drawing order of dataset.

### Point Styling

Expand Down
1 change: 1 addition & 0 deletions docs/charts/scatter.md
Expand Up @@ -32,6 +32,7 @@ var scatterChart = new Chart(ctx, {
```

## Dataset Properties

The scatter chart supports all of the same properties as the [line chart](./line.md#dataset-properties).

## Data Structure
Expand Down
36 changes: 22 additions & 14 deletions src/controllers/controller.bar.js
Expand Up @@ -208,21 +208,27 @@ module.exports = DatasetController.extend({
*/
_getStacks: function(last) {
var me = this;
var chart = me.chart;
var scale = me._getIndexScale();
var metasets = scale._getMatchingVisibleMetas(me._type);
var stacked = scale.options.stacked;
var ilen = last === undefined ? chart.data.datasets.length : last + 1;
var ilen = metasets.length;
var stacks = [];
var i, meta;

for (i = 0; i < ilen; ++i) {
meta = chart.getDatasetMeta(i);
if (meta.bar && chart.isDatasetVisible(i) &&
(stacked === false ||
(stacked === true && stacks.indexOf(meta.stack) === -1) ||
(stacked === undefined && (meta.stack === undefined || stacks.indexOf(meta.stack) === -1)))) {
meta = metasets[i];
// stacked | meta.stack
// | found | not found | undefined
// false | x | x | x
// true | | x |
// undefined | | x | x
if (stacked === false || stacks.indexOf(meta.stack) === -1 ||
etimberg marked this conversation as resolved.
Show resolved Hide resolved
(stacked === undefined && meta.stack === undefined)) {
stacks.push(meta.stack);
}
if (meta.index === last) {
break;
}
}

return stacks;
Expand Down Expand Up @@ -297,24 +303,26 @@ module.exports = DatasetController.extend({
var scale = me._getValueScale();
var isHorizontal = scale.isHorizontal();
var datasets = chart.data.datasets;
var metasets = scale._getMatchingVisibleMetas(me._type);
var value = scale._parseValue(datasets[datasetIndex].data[index]);
var minBarLength = scale.options.minBarLength;
var stacked = scale.options.stacked;
var stack = meta.stack;
var start = value.start === undefined ? 0 : value.max >= 0 && value.min >= 0 ? value.min : value.max;
var length = value.start === undefined ? value.end : value.max >= 0 && value.min >= 0 ? value.max - value.min : value.min - value.max;
var ilen = metasets.length;
var i, imeta, ivalue, base, head, size, stackLength;

if (stacked || (stacked === undefined && stack !== undefined)) {
for (i = 0; i < datasetIndex; ++i) {
imeta = chart.getDatasetMeta(i);
for (i = 0; i < ilen; ++i) {
imeta = metasets[i];

if (imeta.bar &&
imeta.stack === stack &&
imeta.controller._getValueScaleId() === scale.id &&
chart.isDatasetVisible(i)) {
if (imeta.index === datasetIndex) {
break;
}

stackLength = scale._parseValue(datasets[i].data[index]);
if (imeta.stack === stack) {
stackLength = scale._parseValue(datasets[imeta.index].data[index]);
ivalue = stackLength.start === undefined ? stackLength.end : stackLength.min >= 0 && stackLength.max >= 0 ? stackLength.max : stackLength.min;

if ((value.min < 0 && ivalue < 0) || (value.max >= 0 && ivalue > 0)) {
Expand Down
24 changes: 14 additions & 10 deletions src/controllers/controller.line.js
Expand Up @@ -183,14 +183,21 @@ module.exports = DatasetController.extend({
var yScale = me._yScale;
var sumPos = 0;
var sumNeg = 0;
var i, ds, dsMeta;
var rightValue = +yScale.getRightValue(value);
var metasets = chart._getSortedVisibleDatasetMetas();
var ilen = metasets.length;
var i, ds, dsMeta, stackedRightValue;

if (yScale.options.stacked) {
for (i = 0; i < datasetIndex; i++) {
ds = chart.data.datasets[i];
dsMeta = chart.getDatasetMeta(i);
if (dsMeta.type === 'line' && dsMeta.yAxisID === yScale.id && chart.isDatasetVisible(i)) {
var stackedRightValue = Number(yScale.getRightValue(ds.data[index]));
for (i = 0; i < ilen; ++i) {
dsMeta = metasets[i];
if (dsMeta.index === datasetIndex) {
break;
}

ds = chart.data.datasets[dsMeta.index];
if (dsMeta.type === 'line' && dsMeta.yAxisID === yScale.id) {
stackedRightValue = +yScale.getRightValue(ds.data[index]);
if (stackedRightValue < 0) {
sumNeg += stackedRightValue || 0;
} else {
Expand All @@ -199,14 +206,11 @@ module.exports = DatasetController.extend({
}
}

var rightValue = Number(yScale.getRightValue(value));
if (rightValue < 0) {
return yScale.getPixelForValue(sumNeg + rightValue);
}
return yScale.getPixelForValue(sumPos + rightValue);
}

return yScale.getPixelForValue(value);
return yScale.getPixelForValue(sumPos + rightValue);
},

updateBezierControlPoints: function() {
Expand Down
61 changes: 47 additions & 14 deletions src/core/core.controller.js
Expand Up @@ -154,6 +154,14 @@ function positionIsHorizontal(position) {
return position === 'top' || position === 'bottom';
}

function compare2Level(l1, l2) {
return function(a, b) {
return a[l1] === b[l1]
? a[l2] - b[l2]
: a[l1] - b[l1];
};
}

var Chart = function(item, config) {
this.construct(item, config);
return this;
Expand Down Expand Up @@ -422,6 +430,8 @@ helpers.extend(Chart.prototype, /** @lends Chart */ {
meta = me.getDatasetMeta(datasetIndex);
}
meta.type = type;
meta.order = dataset.order || 0;
meta.index = datasetIndex;

if (meta.controller) {
meta.controller.updateIndex(datasetIndex);
Expand Down Expand Up @@ -513,11 +523,7 @@ helpers.extend(Chart.prototype, /** @lends Chart */ {
// Do this before render so that any plugins that need final scale updates can use it
plugins.notify(me, 'afterUpdate');

me._layers.sort(function(a, b) {
return a.z === b.z
? a._idx - b._idx
: a.z - b.z;
});
me._layers.sort(compare2Level('z', '_idx'));

if (me._bufferedRender) {
me._bufferedRequest = {
Expand Down Expand Up @@ -712,23 +718,49 @@ helpers.extend(Chart.prototype, /** @lends Chart */ {
me.tooltip.transition(easingValue);
},

/**
* @private
*/
_getSortedDatasetMetas: function(filterVisible) {
var me = this;
var datasets = me.data.datasets || [];
var result = [];
var i, ilen;

for (i = 0, ilen = datasets.length; i < ilen; ++i) {
if (!filterVisible || me.isDatasetVisible(i)) {
result.push(me.getDatasetMeta(i));
}
}

result.sort(compare2Level('order', 'index'));

return result;
},

/**
* @private
*/
_getSortedVisibleDatasetMetas: function() {
kurkle marked this conversation as resolved.
Show resolved Hide resolved
return this._getSortedDatasetMetas(true);
},

/**
* Draws all datasets unless a plugin returns `false` to the `beforeDatasetsDraw`
* hook, in which case, plugins will not be called on `afterDatasetsDraw`.
* @private
*/
drawDatasets: function(easingValue) {
var me = this;
var metasets, i;

if (plugins.notify(me, 'beforeDatasetsDraw', [easingValue]) === false) {
return;
}

// Draw datasets reversed to support proper line stacking
for (var i = (me.data.datasets || []).length - 1; i >= 0; --i) {
if (me.isDatasetVisible(i)) {
me.drawDataset(i, easingValue);
}
metasets = me._getSortedVisibleDatasetMetas();
for (i = metasets.length - 1; i >= 0; --i) {
me.drawDataset(metasets[i], easingValue);
}

plugins.notify(me, 'afterDatasetsDraw', [easingValue]);
Expand All @@ -739,12 +771,11 @@ helpers.extend(Chart.prototype, /** @lends Chart */ {
* hook, in which case, plugins will not be called on `afterDatasetDraw`.
* @private
*/
drawDataset: function(index, easingValue) {
drawDataset: function(meta, easingValue) {
var me = this;
var meta = me.getDatasetMeta(index);
var args = {
meta: meta,
index: index,
index: meta.index,
easingValue: easingValue
};

Expand Down Expand Up @@ -824,7 +855,9 @@ helpers.extend(Chart.prototype, /** @lends Chart */ {
controller: null,
hidden: null, // See isDatasetVisible() comment
xAxisID: null,
yAxisID: null
yAxisID: null,
order: dataset.order || 0,
index: datasetIndex
};
}

Expand Down
29 changes: 11 additions & 18 deletions src/core/core.interaction.js
Expand Up @@ -25,17 +25,13 @@ function getRelativePosition(e, chart) {
* @param {function} handler - the callback to execute for each visible item
*/
function parseVisibleItems(chart, handler) {
var datasets = chart.data.datasets;
var meta, i, j, ilen, jlen;
var metasets = chart._getSortedVisibleDatasetMetas();
var metadata, i, j, ilen, jlen, element;

for (i = 0, ilen = datasets.length; i < ilen; ++i) {
if (!chart.isDatasetVisible(i)) {
continue;
}

meta = chart.getDatasetMeta(i);
for (j = 0, jlen = meta.data.length; j < jlen; ++j) {
var element = meta.data[j];
for (i = 0, ilen = metasets.length; i < ilen; ++i) {
metadata = metasets[i].data;
for (j = 0, jlen = metadata.length; j < jlen; ++j) {
element = metadata[j];
if (!element._view.skip) {
handler(element);
}
Expand Down Expand Up @@ -120,15 +116,12 @@ function indexMode(chart, e, options) {
return [];
}

chart.data.datasets.forEach(function(dataset, datasetIndex) {
if (chart.isDatasetVisible(datasetIndex)) {
var meta = chart.getDatasetMeta(datasetIndex);
var element = meta.data[items[0]._index];
chart._getSortedVisibleDatasetMetas().forEach(function(meta) {
var element = meta.data[items[0]._index];

// don't count items that are skipped (null data)
if (element && !element._view.skip) {
elements.push(element);
}
// don't count items that are skipped (null data)
if (element && !element._view.skip) {
elements.push(element);
}
});

Expand Down