diff --git a/docs/developers/api.md b/docs/developers/api.md index 4494dfebb9b..a17b2a5d6b7 100644 --- a/docs/developers/api.md +++ b/docs/developers/api.md @@ -152,20 +152,26 @@ Returns the stored visibility state of an data index for all datasets. Set by [t var visible = chart.getDataVisibility(2); ``` -## hide(datasetIndex) +## hide(datasetIndex, dataIndex?) -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. +If dataIndex is not specified, 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. + +If dataIndex is specified, sets the hidden flag of that element to true and updates the chart. ```javascript chart.hide(1); // hides dataset at index 1 and does 'hide' animation. +chart.hide(0, 2); // hides the data element at index 2 of the first dataset. ``` -## show(datasetIndex) +## show(datasetIndex, dataIndex?) + +If dataIndex is not specified, sets the visibility for the given dataset to true. Updates the chart and animates the dataset with `'show'` mode. This animation can be configured under the `show` key in animation options. Please see [animations](../configuration/animations.md) docs for more details. -Sets the visibility for the given dataset to true. Updates the chart and animates the dataset with `'show'` mode. This animation can be configured under the `show` key in animation options. Please see [animations](../configuration/animations.md) docs for more details. +If dataIndex is specified, sets the hidden flag of that element to false and updates the chart. ```javascript chart.show(1); // shows dataset at index 1 and does 'show' animation. +chart.show(0, 2); // shows the data element at index 2 of the first dataset. ``` ## setActiveElements(activeElements) diff --git a/docs/samples/other-charts/doughnut.md b/docs/samples/other-charts/doughnut.md index bbe7d9f894a..21e98c68e48 100644 --- a/docs/samples/other-charts/doughnut.md +++ b/docs/samples/other-charts/doughnut.md @@ -48,6 +48,30 @@ const actions = [ } } }, + { + name: 'Hide(0)', + handler(chart) { + chart.hide(0); + } + }, + { + name: 'Show(0)', + handler(chart) { + chart.show(0); + } + }, + { + name: 'Hide (0, 1)', + handler(chart) { + chart.hide(0, 1); + } + }, + { + name: 'Show (0, 1)', + handler(chart) { + chart.show(0, 1); + } + }, { name: 'Remove Dataset', handler(chart) { diff --git a/src/controllers/controller.doughnut.js b/src/controllers/controller.doughnut.js index 20929bbe1f6..91c4756cf91 100644 --- a/src/controllers/controller.doughnut.js +++ b/src/controllers/controller.doughnut.js @@ -145,7 +145,7 @@ export default class DoughnutController extends DatasetController { const opts = me.options; const meta = me._cachedMeta; const circumference = me._getCircumference(); - if ((reset && opts.animation.animateRotate) || !this.chart.getDataVisibility(i) || meta._parsed[i] === null) { + if ((reset && opts.animation.animateRotate) || !this.chart.getDataVisibility(i) || meta._parsed[i] === null || meta.data[i].hidden) { return 0; } return me.calculateCircumference(meta._parsed[i] * circumference / TAU); @@ -203,7 +203,7 @@ export default class DoughnutController extends DatasetController { for (i = 0; i < metaData.length; i++) { const value = meta._parsed[i]; - if (value !== null && !isNaN(value) && this.chart.getDataVisibility(i)) { + if (value !== null && !isNaN(value) && this.chart.getDataVisibility(i) && !metaData[i].hidden) { total += Math.abs(value); } } diff --git a/src/core/core.controller.js b/src/core/core.controller.js index 16c98cd97ff..96bce6b4ce7 100644 --- a/src/core/core.controller.js +++ b/src/core/core.controller.js @@ -7,7 +7,7 @@ import PluginService from './core.plugins'; import registry from './core.registry'; import Config, {determineAxis, getIndexAxis} from './core.config'; import {retinaScale, _isDomSupported} from '../helpers/helpers.dom'; -import {each, callback as callCallback, uid, valueOrDefault, _elementsEqual, isNullOrUndef, setsEqual} from '../helpers/helpers.core'; +import {each, callback as callCallback, uid, valueOrDefault, _elementsEqual, isNullOrUndef, setsEqual, defined} from '../helpers/helpers.core'; import {clearCanvas, clipArea, unclipArea, _isPointInArea} from '../helpers/helpers.canvas'; // @ts-ignore import {version} from '../../package.json'; @@ -794,25 +794,29 @@ class Chart { /** * @private */ - _updateDatasetVisibility(datasetIndex, visible) { + _updateVisibility(datasetIndex, dataIndex, visible) { const me = this; const mode = visible ? 'show' : 'hide'; const meta = me.getDatasetMeta(datasetIndex); const anims = meta.controller._resolveAnimations(undefined, mode); - me.setDatasetVisibility(datasetIndex, visible); - // Animate visible state, so hide animation can be seen. This could be handled better if update / updateDataset returned a Promise. - anims.update(meta, {visible}); - - me.update((ctx) => ctx.datasetIndex === datasetIndex ? mode : undefined); + if (defined(dataIndex)) { + meta.data[dataIndex].hidden = !visible; + me.update(); + } else { + me.setDatasetVisibility(datasetIndex, visible); + // Animate visible state, so hide animation can be seen. This could be handled better if update / updateDataset returned a Promise. + anims.update(meta, {visible}); + me.update((ctx) => ctx.datasetIndex === datasetIndex ? mode : undefined); + } } - hide(datasetIndex) { - this._updateDatasetVisibility(datasetIndex, false); + hide(datasetIndex, dataIndex) { + this._updateVisibility(datasetIndex, dataIndex, false); } - show(datasetIndex) { - this._updateDatasetVisibility(datasetIndex, true); + show(datasetIndex, dataIndex) { + this._updateVisibility(datasetIndex, dataIndex, true); } /** diff --git a/src/core/core.datasetController.js b/src/core/core.datasetController.js index 048073a8400..f504d3f5cbf 100644 --- a/src/core/core.datasetController.js +++ b/src/core/core.datasetController.js @@ -701,6 +701,9 @@ export default class DatasetController { for (i = start; i < start + count; ++i) { const element = elements[i]; + if (element.hidden) { + continue; + } if (element.active) { active.push(element); } else { diff --git a/test/fixtures/controller.doughnut/doughnut-hidden-single.js b/test/fixtures/controller.doughnut/doughnut-hidden-single.js new file mode 100644 index 00000000000..80f0ee9f795 --- /dev/null +++ b/test/fixtures/controller.doughnut/doughnut-hidden-single.js @@ -0,0 +1,42 @@ +module.exports = { + config: { + type: 'doughnut', + data: { + labels: ['A', 'B', 'C', 'D', 'E'], + datasets: [{ + data: [1, 5, 10, 50, 100], + backgroundColor: [ + 'rgba(255, 99, 132, 0.8)', + 'rgba(54, 162, 235, 0.8)', + 'rgba(255, 206, 86, 0.8)', + 'rgba(75, 192, 192, 0.8)', + 'rgba(153, 102, 255, 0.8)' + ], + }, { + data: [1, 5, 10, 50, 100], + backgroundColor: [ + 'rgba(255, 99, 132, 0.8)', + 'rgba(54, 162, 235, 0.8)', + 'rgba(255, 206, 86, 0.8)', + 'rgba(75, 192, 192, 0.8)', + 'rgba(153, 102, 255, 0.8)' + ], + }] + }, + options: { + responsive: false, + plugins: { + legend: false, + title: false, + tooltip: false, + filler: false + } + }, + }, + options: { + run(chart) { + chart.hide(0, 4); + chart.hide(1, 2); + } + } +}; diff --git a/test/fixtures/controller.doughnut/doughnut-hidden-single.png b/test/fixtures/controller.doughnut/doughnut-hidden-single.png new file mode 100644 index 00000000000..5cfbe2c02d2 Binary files /dev/null and b/test/fixtures/controller.doughnut/doughnut-hidden-single.png differ diff --git a/types/index.esm.d.ts b/types/index.esm.d.ts index 4b1e36e402f..8b4cb0cd117 100644 --- a/types/index.esm.d.ts +++ b/types/index.esm.d.ts @@ -505,8 +505,8 @@ export declare class Chart< setDatasetVisibility(datasetIndex: number, visible: boolean): void; toggleDataVisibility(index: number): void; getDataVisibility(index: number): boolean; - hide(datasetIndex: number): void; - show(datasetIndex: number): void; + hide(datasetIndex: number, dataIndex?: number): void; + show(datasetIndex: number, dataIndex?: number): void; getActiveElements(): ActiveElement[]; setActiveElements(active: ActiveDataPoint[]): void;