]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Handle data visibility per chart
authorSimon Brunel <simonbrunel@users.noreply.github.com>
Sat, 23 Apr 2016 08:57:29 +0000 (10:57 +0200)
committerSimon Brunel <simonbrunel@users.noreply.github.com>
Tue, 26 Apr 2016 10:46:29 +0000 (12:46 +0200)
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.

src/controllers/controller.doughnut.js
src/controllers/controller.polarArea.js
src/core/core.controller.js
src/core/core.element.js
src/scales/scale.linear.js
src/scales/scale.logarithmic.js
src/scales/scale.radialLinear.js

index 69a5a130ffcb9cef4483903fb9eb8e54dbba4911..6044dc893c11f4b0eae12092ac92a9daaaa1bb6b 100644 (file)
@@ -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;
                        }
index 19e9b4b0d8ea077203bca2e17e14dbba562d9296..c7dd87cad29bbe513f3d86cb5ac20956b515fc28 100644 (file)
@@ -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
+};
index 6ace65e8e85d96b3594119f6a5eb4985e9f35917..6684c1e39ad0681498bcdba304cc28a25b22e8d8 100644 (file)
@@ -416,7 +416,6 @@ module.exports = function(Chart) {
                                data: [],
                                dataset: null,
                                controller: null,
-                               hiddenData: {},
                                hidden: null,                   // See isDatasetVisible() comment
                                xAxisID: null,
                                yAxisID: null
index e9e2a05ef0da0c3c407762ff0a322c26c2d7b378..f411647157a9caa9d39a86cb5992021032f5b773 100644 (file)
@@ -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);
index c2717f30b17277a5041a1c738bed092d931e8875..918db2cd3f1b78b94a0f7db0a80eec5821c5bbc4 100644 (file)
@@ -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;
                                                        }
 
index ef9ab1435cec2cef2f1e2144c326564cccad0055..a6fe02ae2b684ebe939ec118da55c8d208ed966f 100644 (file)
@@ -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;
                                                        }
 
index e381a18e6d117c814ed14f3bac340775b008d57a..11b9b2417875d59c1ebd619340f23897dfb7aa17 100644 (file)
@@ -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;
                                                }