From: Simon Brunel Date: Sat, 23 Apr 2016 08:57:29 +0000 (+0200) Subject: Handle data visibility per chart X-Git-Tag: 2.1.0~13^2~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=29115c9d2c94f5f52a22fa5e9d39244726a7d9d2;p=thirdparty%2FChart.js.git Handle data visibility per chart New Chart.Element.hidden bool flag storing the visibility state of its associated data. Since elements belong to a specific chart, this change allows to manage data visibility per chart (e.g. when clicking the legend of some charts). This commit also changes (fixes?) the polar chart animation when data visibility changes. Previous implementation was affected by an edge effect due to the use of NaN as hidden implementation. --- diff --git a/src/controllers/controller.doughnut.js b/src/controllers/controller.doughnut.js index 69a5a130f..6044dc893 100644 --- a/src/controllers/controller.doughnut.js +++ b/src/controllers/controller.doughnut.js @@ -38,8 +38,9 @@ module.exports = function(Chart) { var data = chart.data; if (data.labels.length && data.datasets.length) { return data.labels.map(function(label, i) { + var meta = chart.getDatasetMeta(0); var ds = data.datasets[0]; - var arc = chart.getDatasetMeta(0).data[i]; + var arc = meta.data[i]; var fill = arc.custom && arc.custom.backgroundColor ? arc.custom.backgroundColor : helpers.getValueAtIndexOrDefault(ds.backgroundColor, i, this.chart.options.elements.arc.backgroundColor); var stroke = arc.custom && arc.custom.borderColor ? arc.custom.borderColor : helpers.getValueAtIndexOrDefault(ds.borderColor, i, this.chart.options.elements.arc.borderColor); var bw = arc.custom && arc.custom.borderWidth ? arc.custom.borderWidth : helpers.getValueAtIndexOrDefault(ds.borderWidth, i, this.chart.options.elements.arc.borderWidth); @@ -49,7 +50,7 @@ module.exports = function(Chart) { fillStyle: fill, strokeStyle: stroke, lineWidth: bw, - hidden: isNaN(data.datasets[0].data[i]), + hidden: isNaN(ds.data[i]) || meta.data[i].hidden, // Extra data used for toggling the correct item index: i @@ -60,20 +61,18 @@ module.exports = function(Chart) { } } }, + onClick: function(e, legendItem) { - helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) { - var meta = this.chart.getDatasetMeta(datasetIndex); - var idx = legendItem.index; - - if (!isNaN(dataset.data[idx])) { - meta.hiddenData[idx] = dataset.data[idx]; - dataset.data[idx] = NaN; - } else if (!isNaN(meta.hiddenData[idx])) { - dataset.data[idx] = meta.hiddenData[idx]; - } - }, this); + var index = legendItem.index; + var chart = this.chart; + var 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; + } - this.chart.update(); + chart.update(); } }, @@ -181,12 +180,7 @@ module.exports = function(Chart) { this.chart.offsetX = offset.x * this.chart.outerRadius; this.chart.offsetY = offset.y * this.chart.outerRadius; - this.getDataset().total = 0; - helpers.each(this.getDataset().data, function(value) { - if (!isNaN(value)) { - this.getDataset().total += Math.abs(value); - } - }, this); + this.getMeta().total = this.calculateTotal(); this.outerRadius = this.chart.outerRadius - (this.chart.radiusLength * this.getRingIndex(this.index)); this.innerRadius = this.outerRadius - this.chart.radiusLength; @@ -195,12 +189,13 @@ module.exports = function(Chart) { this.updateElement(arc, index, reset); }, this); }, + updateElement: function(arc, index, reset) { var centerX = (this.chart.chartArea.left + this.chart.chartArea.right) / 2; var centerY = (this.chart.chartArea.top + this.chart.chartArea.bottom) / 2; var startAngle = this.chart.options.rotation; // non reset case handled later var endAngle = this.chart.options.rotation; // non reset case handled later - var circumference = reset && this.chart.options.animation.animateRotate ? 0 : this.calculateCircumference(this.getDataset().data[index]) * (this.chart.options.circumference / (2.0 * Math.PI)); + var circumference = reset && this.chart.options.animation.animateRotate ? 0 : arc.hidden? 0 : this.calculateCircumference(this.getDataset().data[index]) * (this.chart.options.circumference / (2.0 * Math.PI)); var innerRadius = reset && this.chart.options.animation.animateScale ? 0 : this.innerRadius; var outerRadius = reset && this.chart.options.animation.animateScale ? 0 : this.outerRadius; @@ -269,9 +264,23 @@ module.exports = function(Chart) { arc._model.borderWidth = arc.custom && arc.custom.borderWidth ? arc.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().borderWidth, index, this.chart.options.elements.arc.borderWidth); }, + calculateTotal: function() { + var meta = this.getMeta(); + var total = 0; + + this.getDataset().data.forEach(function(value, index) { + if (!isNaN(value) && !meta.data[index].hidden) { + total += Math.abs(value); + } + }); + + return total; + }, + calculateCircumference: function(value) { - if (this.getDataset().total > 0 && !isNaN(value)) { - return (Math.PI * 2.0) * (value / this.getDataset().total); + var total = this.getMeta().total; + if (total > 0 && !isNaN(value)) { + return (Math.PI * 2.0) * (value / total); } else { return 0; } diff --git a/src/controllers/controller.polarArea.js b/src/controllers/controller.polarArea.js index 19e9b4b0d..c7dd87cad 100644 --- a/src/controllers/controller.polarArea.js +++ b/src/controllers/controller.polarArea.js @@ -39,8 +39,9 @@ module.exports = function(Chart) { var data = chart.data; if (data.labels.length && data.datasets.length) { return data.labels.map(function(label, i) { + var meta = chart.getDatasetMeta(0); var ds = data.datasets[0]; - var arc = chart.getDatasetMeta(0).data[i]; + var arc = meta.data[i]; var fill = arc.custom && arc.custom.backgroundColor ? arc.custom.backgroundColor : helpers.getValueAtIndexOrDefault(ds.backgroundColor, i, this.chart.options.elements.arc.backgroundColor); var stroke = arc.custom && arc.custom.borderColor ? arc.custom.borderColor : helpers.getValueAtIndexOrDefault(ds.borderColor, i, this.chart.options.elements.arc.borderColor); var bw = arc.custom && arc.custom.borderWidth ? arc.custom.borderWidth : helpers.getValueAtIndexOrDefault(ds.borderWidth, i, this.chart.options.elements.arc.borderWidth); @@ -50,7 +51,7 @@ module.exports = function(Chart) { fillStyle: fill, strokeStyle: stroke, lineWidth: bw, - hidden: isNaN(data.datasets[0].data[i]), + hidden: isNaN(ds.data[i]) || meta.data[i].hidden, // Extra data used for toggling the correct item index: i @@ -61,20 +62,18 @@ module.exports = function(Chart) { } } }, + onClick: function(e, legendItem) { - helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) { - var meta = this.chart.getDatasetMeta(datasetIndex); - var idx = legendItem.index; - - if (!isNaN(dataset.data[idx])) { - meta.hiddenData[idx] = dataset.data[idx]; - dataset.data[idx] = NaN; - } else if (!isNaN(meta.hiddenData[idx])) { - dataset.data[idx] = meta.hiddenData[idx]; - } - }, this); + var index = legendItem.index; + var chart = this.chart; + var 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; + } - this.chart.update(); + chart.update(); } }, @@ -125,11 +124,6 @@ module.exports = function(Chart) { this.chart.innerRadius = Math.max(this.chart.options.cutoutPercentage ? (this.chart.outerRadius / 100) * (this.chart.options.cutoutPercentage) : 1, 0); this.chart.radiusLength = (this.chart.outerRadius - this.chart.innerRadius) / this.chart.getVisibleDatasetCount(); - this.getDataset().total = 0; - helpers.each(this.getDataset().data, function(value) { - this.getDataset().total += Math.abs(value); - }, this); - this.outerRadius = this.chart.outerRadius - (this.chart.radiusLength * this.index); this.innerRadius = this.outerRadius - this.chart.radiusLength; @@ -145,21 +139,23 @@ module.exports = function(Chart) { // If there is NaN data before us, we need to calculate the starting angle correctly. // We could be way more efficient here, but its unlikely that the polar area chart will have a lot of data - var notNullIndex = 0; + var visibleCount = 0; + var meta = this.getMeta(); for (var i = 0; i < index; ++i) { - if (!isNaN(this.getDataset().data[i])) { - ++notNullIndex; + if (!isNaN(this.getDataset().data[i]) && !meta.data[i].hidden) { + ++visibleCount; } } - var startAngle = (-0.5 * Math.PI) + (circumference * notNullIndex); - var endAngle = startAngle + circumference; + var distance = arc.hidden? 0 : this.chart.scale.getDistanceFromCenterForValue(this.getDataset().data[index]); + var startAngle = (-0.5 * Math.PI) + (circumference * visibleCount); + var endAngle = startAngle + (arc.hidden? 0 : circumference); var resetModel = { x: centerX, y: centerY, innerRadius: 0, - outerRadius: this.chart.options.animateScale ? 0 : this.chart.scale.getDistanceFromCenterForValue(this.getDataset().data[index]), + outerRadius: this.chart.options.animateScale ? 0 : distance, startAngle: this.chart.options.animateRotate ? Math.PI * -0.5 : startAngle, endAngle: this.chart.options.animateRotate ? Math.PI * -0.5 : endAngle, @@ -182,7 +178,7 @@ module.exports = function(Chart) { x: centerX, y: centerY, innerRadius: 0, - outerRadius: this.chart.scale.getDistanceFromCenterForValue(this.getDataset().data[index]), + outerRadius: distance, startAngle: startAngle, endAngle: endAngle, @@ -225,15 +221,20 @@ module.exports = function(Chart) { calculateCircumference: function(value) { if (isNaN(value)) { return 0; - } else { - // Count the number of NaN values - var numNaN = helpers.where(this.getDataset().data, function(data) { - return isNaN(data); - }).length; - - return (2 * Math.PI) / (this.getDataset().data.length - numNaN); } + + // Count the number of "visible"" values + var meta = this.getMeta(); + var count = 0; + + this.getDataset().data.forEach(function(value, index) { + if (!isNaN(value) && !meta.data[index].hidden) { + count++; + } + }); + + return (2 * Math.PI) / count; } }); -}; \ No newline at end of file +}; diff --git a/src/core/core.controller.js b/src/core/core.controller.js index 6ace65e8e..6684c1e39 100644 --- a/src/core/core.controller.js +++ b/src/core/core.controller.js @@ -416,7 +416,6 @@ module.exports = function(Chart) { data: [], dataset: null, controller: null, - hiddenData: {}, hidden: null, // See isDatasetVisible() comment xAxisID: null, yAxisID: null diff --git a/src/core/core.element.js b/src/core/core.element.js index e9e2a05ef..f41164715 100644 --- a/src/core/core.element.js +++ b/src/core/core.element.js @@ -11,7 +11,9 @@ module.exports = function(Chart) { this.initialize.apply(this, arguments); }; helpers.extend(Chart.Element.prototype, { - initialize: function() {}, + initialize: function() { + this.hidden = false; + }, pivot: function() { if (!this._view) { this._view = helpers.clone(this._model); diff --git a/src/scales/scale.linear.js b/src/scales/scale.linear.js index c2717f30b..918db2cd3 100644 --- a/src/scales/scale.linear.js +++ b/src/scales/scale.linear.js @@ -61,9 +61,8 @@ module.exports = function(Chart) { if (this.chart.isDatasetVisible(datasetIndex) && (this.isHorizontal() ? meta.xAxisID === this.id : meta.yAxisID === this.id)) { helpers.each(dataset.data, function(rawValue, index) { - var value = +this.getRightValue(rawValue); - if (isNaN(value)) { + if (isNaN(value) || meta.data[index].hidden) { return; } @@ -99,7 +98,7 @@ module.exports = function(Chart) { if (this.chart.isDatasetVisible(datasetIndex) && (this.isHorizontal() ? meta.xAxisID === this.id : meta.yAxisID === this.id)) { helpers.each(dataset.data, function(rawValue, index) { var value = +this.getRightValue(rawValue); - if (isNaN(value)) { + if (isNaN(value) || meta.data[index].hidden) { return; } diff --git a/src/scales/scale.logarithmic.js b/src/scales/scale.logarithmic.js index ef9ab1435..a6fe02ae2 100644 --- a/src/scales/scale.logarithmic.js +++ b/src/scales/scale.logarithmic.js @@ -40,7 +40,7 @@ module.exports = function(Chart) { helpers.each(dataset.data, function(rawValue, index) { var values = valuesPerType[meta.type]; var value = +this.getRightValue(rawValue); - if (isNaN(value)) { + if (isNaN(value) || meta.data[index].hidden) { return; } @@ -66,10 +66,10 @@ module.exports = function(Chart) { } else { helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) { var meta = this.chart.getDatasetMeta(datasetIndex); - if (this.chart.isDatasetVisible(dataset, datasetIndex) && (this.isHorizontal() ? meta.xAxisID === this.id : meta.yAxisID === this.id)) { + if (this.chart.isDatasetVisible(datasetIndex) && (this.isHorizontal() ? meta.xAxisID === this.id : meta.yAxisID === this.id)) { helpers.each(dataset.data, function(rawValue, index) { var value = +this.getRightValue(rawValue); - if (isNaN(value)) { + if (isNaN(value) || meta.data[index].hidden) { return; } diff --git a/src/scales/scale.radialLinear.js b/src/scales/scale.radialLinear.js index e381a18e6..11b9b2417 100644 --- a/src/scales/scale.radialLinear.js +++ b/src/scales/scale.radialLinear.js @@ -65,9 +65,10 @@ module.exports = function(Chart) { helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) { if (this.chart.isDatasetVisible(datasetIndex)) { + var meta = this.chart.getDatasetMeta(datasetIndex); helpers.each(dataset.data, function(rawValue, index) { var value = +this.getRightValue(rawValue); - if (isNaN(value)) { + if (isNaN(value) || meta.data[index].hidden) { return; }