Use global element hidden status for Pie charts (#7156)

Use global element hidden status for Pie / polarArea charts
This commit is contained in:
Jukka Kurkela 2020-03-01 16:07:39 +02:00 committed by GitHub
parent 3b915cbdd3
commit a3dddb45d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 52 additions and 55 deletions

View File

@ -166,6 +166,23 @@ chart.setDataVisibility(0, 2, false); // hides the item in dataset 0, at index 2
chart.update(); // chart now renders with item hidden
```
## toggleDataVisibility(index)
Toggles the visibility of an item in all datasets. A dataset needs to explicitly support this feature for it to have an effect. From internal chart types, doughnut / pie and polar area use this.
```javascript
chart.toggleDataVisibility(2); // toggles the item in all datasets, at index 2
chart.update(); // chart now renders with item hidden
```
## getDataVisibility(index)
Returns the stored visibility state of an data index for all datasets. Set by [toggleDataVisibility](#toggleDataVisibility). A dataset controller should use this method to determine if an item should not be visible.
```javascript
var visible = chart.getDataVisibility(2);
```
## hide(datasetIndex)
Sets the visibility for the given dataset to false. Updates the chart and animates the dataset with `'hide'` mode. This animation can be configured under the `hide` key in animation options. Please see [animations](../configuration/animations.md) docs for more details.

View File

@ -104,6 +104,7 @@ Animation system was completely rewritten in Chart.js v3. Each property can now
* `DatasetController.createMetaDataset`
* `Element.getArea`
* `Element.height`
* `Element.hidden` was replaced by chart level status, usable with `getDataVisibility(index)` / `toggleDataVisibility(index)`
* `Element.initialize`
* `Element.inLabelRange`
* `helpers.addEvent`

View File

@ -36,7 +36,7 @@ defaults.set('doughnut', {
fillStyle: style.backgroundColor,
strokeStyle: style.borderColor,
lineWidth: style.borderWidth,
hidden: isNaN(data.datasets[0].data[i]) || meta.data[i].hidden,
hidden: !chart.getDataVisibility(i),
// Extra data used for toggling the correct item
index: i
@ -48,19 +48,8 @@ defaults.set('doughnut', {
},
onClick(e, legendItem) {
const index = legendItem.index;
const chart = this.chart;
let i, ilen, meta;
for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {
meta = chart.getDatasetMeta(i);
// toggle visibility of index if exists
if (meta.data[index]) {
meta.data[index].hidden = !meta.data[index].hidden;
}
}
chart.update();
this.chart.toggleDataVisibility(legendItem.index);
this.chart.update();
}
},
@ -202,7 +191,7 @@ export default class DoughnutController extends DatasetController {
const me = this;
const opts = me.chart.options;
const meta = me._cachedMeta;
return reset && opts.animation.animateRotate ? 0 : meta.data[i].hidden ? 0 : me.calculateCircumference(meta._parsed[i] * opts.circumference / DOUBLE_PI);
return reset && opts.animation.animateRotate ? 0 : this.chart.getDataVisibility(i) ? me.calculateCircumference(meta._parsed[i] * opts.circumference / DOUBLE_PI) : 0;
}
updateElements(arcs, start, mode) {
@ -258,7 +247,7 @@ export default class DoughnutController extends DatasetController {
for (i = 0; i < metaData.length; i++) {
const value = meta._parsed[i];
if (!isNaN(value) && !metaData[i].hidden) {
if (!isNaN(value) && this.chart.getDataVisibility(i)) {
total += Math.abs(value);
}
}

View File

@ -44,7 +44,7 @@ defaults.set('polarArea', {
fillStyle: style.backgroundColor,
strokeStyle: style.borderColor,
lineWidth: style.borderWidth,
hidden: isNaN(data.datasets[0].data[i]) || meta.data[i].hidden,
hidden: !chart.getDataVisibility(i),
// Extra data used for toggling the correct item
index: i
@ -56,16 +56,8 @@ defaults.set('polarArea', {
},
onClick(e, legendItem) {
const index = legendItem.index;
const chart = this.chart;
let i, ilen, meta;
for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {
meta = chart.getDatasetMeta(i);
meta.data[index].hidden = !meta.data[index].hidden;
}
chart.update();
this.chart.toggleDataVisibility(legendItem.index);
this.chart.update();
}
},
@ -160,7 +152,7 @@ export default class PolarAreaController extends DatasetController {
const index = start + i;
let startAngle = angle;
let endAngle = angle + me._computeAngle(index);
let outerRadius = arc.hidden ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]);
let outerRadius = this.chart.getDataVisibility(index) ? scale.getDistanceFromCenterForValue(dataset.data[index]) : 0;
angle = endAngle;
if (reset) {
@ -193,7 +185,7 @@ export default class PolarAreaController extends DatasetController {
let count = 0;
meta.data.forEach((element, index) => {
if (!isNaN(dataset.data[index]) && !element.hidden) {
if (!isNaN(dataset.data[index]) && this.chart.getDataVisibility(index)) {
count++;
}
});
@ -210,7 +202,7 @@ export default class PolarAreaController extends DatasetController {
const count = meta.count;
const dataset = me.getDataset();
if (isNaN(dataset.data[index]) || meta.data[index].hidden) {
if (isNaN(dataset.data[index]) || !this.chart.getDataVisibility(index)) {
return 0;
}

View File

@ -222,6 +222,7 @@ export default class Chart {
this.scale = undefined;
this.$plugins = undefined;
this.$proxies = {};
this._hiddenIndices = {};
// Add the chart instance to the global namespace
Chart.instances[me.id] = me;
@ -864,12 +865,12 @@ export default class Chart {
meta.hidden = !visible;
}
setDataVisibility(datasetIndex, index, visible) {
const meta = this.getDatasetMeta(datasetIndex);
toggleDataVisibility(index) {
this._hiddenIndices[index] = !this._hiddenIndices[index];
}
if (meta.data[index]) {
meta.data[index].hidden = !visible;
}
getDataVisibility(index) {
return !this._hiddenIndices[index];
}
/**

View File

@ -624,7 +624,7 @@ export default class DatasetController {
*/
getMinMax(scale, canStack) {
const meta = this._cachedMeta;
const {data, _parsed} = meta;
const _parsed = meta._parsed;
const sorted = meta._sorted && scale === meta.iScale;
const ilen = _parsed.length;
const otherScale = this._getOtherScale(scale);
@ -632,7 +632,7 @@ export default class DatasetController {
let min = Number.POSITIVE_INFINITY;
let max = Number.NEGATIVE_INFINITY;
const {min: otherMin, max: otherMax} = getUserBounds(otherScale);
let i, item, value, parsed, otherValue;
let i, value, parsed, otherValue;
function _compute() {
if (stack) {
@ -648,11 +648,10 @@ export default class DatasetController {
}
function _skip() {
item = data[i];
parsed = _parsed[i];
value = parsed[scale.axis];
otherValue = parsed[otherScale.axis];
return ((item && item.hidden) || isNaN(value) || otherMin > otherValue || otherMax < otherValue);
return (isNaN(value) || otherMin > otherValue || otherMax < otherValue);
}
for (i = 0; i < ilen; ++i) {

View File

@ -8,7 +8,6 @@ export default class Element {
constructor(cfg) {
this.x = undefined;
this.y = undefined;
this.hidden = false;
this.active = false;
this.options = undefined;
this.$animations = undefined;

View File

@ -1365,9 +1365,9 @@ describe('Chart', function() {
expect(meta.hidden).toBe(true);
});
it('should hide a single data item', function() {
it('should toggle data visibility by index', function() {
var chart = acquireChart({
type: 'polarArea',
type: 'pie',
data: {
datasets: [{
data: [1, 2, 3]
@ -1375,10 +1375,13 @@ describe('Chart', function() {
}
});
chart.setDataVisibility(0, 1, false);
expect(chart.getDataVisibility(1)).toBe(true);
var meta = chart.getDatasetMeta(0);
expect(meta.data[1].hidden).toBe(true);
chart.toggleDataVisibility(1);
expect(chart.getDataVisibility(1)).toBe(false);
chart.update();
expect(chart.getDataVisibility(1)).toBe(false);
});
});
});

View File

@ -121,7 +121,7 @@ describe('Default Configs', function() {
}, {
text: 'label3',
fillStyle: 'blue',
hidden: true,
hidden: false,
index: 2,
strokeStyle: '#000',
lineWidth: 2
@ -144,18 +144,16 @@ describe('Default Configs', function() {
},
options: config
});
var meta = chart.getDatasetMeta(0);
spyOn(chart, 'update').and.callThrough();
var legendItem = chart.legend.legendItems[0];
config.legend.onClick.call(chart.legend, null, legendItem);
expect(meta.data[0].hidden).toBe(true);
expect(chart.getDataVisibility(0)).toBe(false);
expect(chart.update).toHaveBeenCalled();
config.legend.onClick.call(chart.legend, null, legendItem);
expect(meta.data[0].hidden).toBe(false);
expect(chart.getDataVisibility(0)).toBe(true);
});
});
@ -219,7 +217,7 @@ describe('Default Configs', function() {
}, {
text: 'label3',
fillStyle: 'blue',
hidden: true,
hidden: false,
index: 2,
strokeStyle: '#000',
lineWidth: 2
@ -242,18 +240,16 @@ describe('Default Configs', function() {
},
options: config
});
var meta = chart.getDatasetMeta(0);
spyOn(chart, 'update').and.callThrough();
var legendItem = chart.legend.legendItems[0];
config.legend.onClick.call(chart.legend, null, legendItem);
expect(meta.data[0].hidden).toBe(true);
expect(chart.getDataVisibility(0)).toBe(false);
expect(chart.update).toHaveBeenCalled();
config.legend.onClick.call(chart.legend, null, legendItem);
expect(meta.data[0].hidden).toBe(false);
expect(chart.getDataVisibility(0)).toBe(true);
});
});
});