Skip to content

Commit 4935990

Browse files
committed
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.
1 parent 9064ecc commit 4935990

File tree

7 files changed

+77
-66
lines changed

7 files changed

+77
-66
lines changed

src/controllers/controller.doughnut.js

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@ module.exports = function(Chart) {
3838
var data = chart.data;
3939
if (data.labels.length && data.datasets.length) {
4040
return data.labels.map(function(label, i) {
41+
var meta = chart.getDatasetMeta(0);
4142
var ds = data.datasets[0];
42-
var arc = chart.getDatasetMeta(0).data[i];
43+
var arc = meta.data[i];
4344
var fill = arc.custom && arc.custom.backgroundColor ? arc.custom.backgroundColor : helpers.getValueAtIndexOrDefault(ds.backgroundColor, i, this.chart.options.elements.arc.backgroundColor);
4445
var stroke = arc.custom && arc.custom.borderColor ? arc.custom.borderColor : helpers.getValueAtIndexOrDefault(ds.borderColor, i, this.chart.options.elements.arc.borderColor);
4546
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) {
4950
fillStyle: fill,
5051
strokeStyle: stroke,
5152
lineWidth: bw,
52-
hidden: isNaN(data.datasets[0].data[i]),
53+
hidden: isNaN(ds.data[i]) || meta.data[i].hidden,
5354

5455
// Extra data used for toggling the correct item
5556
index: i
@@ -60,20 +61,18 @@ module.exports = function(Chart) {
6061
}
6162
}
6263
},
64+
6365
onClick: function(e, legendItem) {
64-
helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {
65-
var meta = this.chart.getDatasetMeta(datasetIndex);
66-
var idx = legendItem.index;
67-
68-
if (!isNaN(dataset.data[idx])) {
69-
meta.hiddenData[idx] = dataset.data[idx];
70-
dataset.data[idx] = NaN;
71-
} else if (!isNaN(meta.hiddenData[idx])) {
72-
dataset.data[idx] = meta.hiddenData[idx];
73-
}
74-
}, this);
66+
var index = legendItem.index;
67+
var chart = this.chart;
68+
var i, ilen, meta;
69+
70+
for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {
71+
meta = chart.getDatasetMeta(i);
72+
meta.data[index].hidden = !meta.data[index].hidden;
73+
}
7574

76-
this.chart.update();
75+
chart.update();
7776
}
7877
},
7978

@@ -181,12 +180,7 @@ module.exports = function(Chart) {
181180
this.chart.offsetX = offset.x * this.chart.outerRadius;
182181
this.chart.offsetY = offset.y * this.chart.outerRadius;
183182

184-
this.getDataset().total = 0;
185-
helpers.each(this.getDataset().data, function(value) {
186-
if (!isNaN(value)) {
187-
this.getDataset().total += Math.abs(value);
188-
}
189-
}, this);
183+
this.getMeta().total = this.calculateTotal();
190184

191185
this.outerRadius = this.chart.outerRadius - (this.chart.radiusLength * this.getRingIndex(this.index));
192186
this.innerRadius = this.outerRadius - this.chart.radiusLength;
@@ -195,12 +189,13 @@ module.exports = function(Chart) {
195189
this.updateElement(arc, index, reset);
196190
}, this);
197191
},
192+
198193
updateElement: function(arc, index, reset) {
199194
var centerX = (this.chart.chartArea.left + this.chart.chartArea.right) / 2;
200195
var centerY = (this.chart.chartArea.top + this.chart.chartArea.bottom) / 2;
201196
var startAngle = this.chart.options.rotation; // non reset case handled later
202197
var endAngle = this.chart.options.rotation; // non reset case handled later
203-
var circumference = reset && this.chart.options.animation.animateRotate ? 0 : this.calculateCircumference(this.getDataset().data[index]) * (this.chart.options.circumference / (2.0 * Math.PI));
198+
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));
204199
var innerRadius = reset && this.chart.options.animation.animateScale ? 0 : this.innerRadius;
205200
var outerRadius = reset && this.chart.options.animation.animateScale ? 0 : this.outerRadius;
206201

@@ -269,9 +264,23 @@ module.exports = function(Chart) {
269264
arc._model.borderWidth = arc.custom && arc.custom.borderWidth ? arc.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().borderWidth, index, this.chart.options.elements.arc.borderWidth);
270265
},
271266

267+
calculateTotal: function() {
268+
var meta = this.getMeta();
269+
var total = 0;
270+
271+
this.getDataset().data.forEach(function(value, index) {
272+
if (!isNaN(value) && !meta.data[index].hidden) {
273+
total += Math.abs(value);
274+
}
275+
});
276+
277+
return total;
278+
},
279+
272280
calculateCircumference: function(value) {
273-
if (this.getDataset().total > 0 && !isNaN(value)) {
274-
return (Math.PI * 2.0) * (value / this.getDataset().total);
281+
var total = this.getMeta().total;
282+
if (total > 0 && !isNaN(value)) {
283+
return (Math.PI * 2.0) * (value / total);
275284
} else {
276285
return 0;
277286
}

src/controllers/controller.polarArea.js

Lines changed: 35 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,9 @@ module.exports = function(Chart) {
3939
var data = chart.data;
4040
if (data.labels.length && data.datasets.length) {
4141
return data.labels.map(function(label, i) {
42+
var meta = chart.getDatasetMeta(0);
4243
var ds = data.datasets[0];
43-
var arc = chart.getDatasetMeta(0).data[i];
44+
var arc = meta.data[i];
4445
var fill = arc.custom && arc.custom.backgroundColor ? arc.custom.backgroundColor : helpers.getValueAtIndexOrDefault(ds.backgroundColor, i, this.chart.options.elements.arc.backgroundColor);
4546
var stroke = arc.custom && arc.custom.borderColor ? arc.custom.borderColor : helpers.getValueAtIndexOrDefault(ds.borderColor, i, this.chart.options.elements.arc.borderColor);
4647
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) {
5051
fillStyle: fill,
5152
strokeStyle: stroke,
5253
lineWidth: bw,
53-
hidden: isNaN(data.datasets[0].data[i]),
54+
hidden: isNaN(ds.data[i]) || meta.data[i].hidden,
5455

5556
// Extra data used for toggling the correct item
5657
index: i
@@ -61,20 +62,18 @@ module.exports = function(Chart) {
6162
}
6263
}
6364
},
65+
6466
onClick: function(e, legendItem) {
65-
helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {
66-
var meta = this.chart.getDatasetMeta(datasetIndex);
67-
var idx = legendItem.index;
68-
69-
if (!isNaN(dataset.data[idx])) {
70-
meta.hiddenData[idx] = dataset.data[idx];
71-
dataset.data[idx] = NaN;
72-
} else if (!isNaN(meta.hiddenData[idx])) {
73-
dataset.data[idx] = meta.hiddenData[idx];
74-
}
75-
}, this);
67+
var index = legendItem.index;
68+
var chart = this.chart;
69+
var i, ilen, meta;
70+
71+
for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {
72+
meta = chart.getDatasetMeta(i);
73+
meta.data[index].hidden = !meta.data[index].hidden;
74+
}
7675

77-
this.chart.update();
76+
chart.update();
7877
}
7978
},
8079

@@ -125,11 +124,6 @@ module.exports = function(Chart) {
125124
this.chart.innerRadius = Math.max(this.chart.options.cutoutPercentage ? (this.chart.outerRadius / 100) * (this.chart.options.cutoutPercentage) : 1, 0);
126125
this.chart.radiusLength = (this.chart.outerRadius - this.chart.innerRadius) / this.chart.getVisibleDatasetCount();
127126

128-
this.getDataset().total = 0;
129-
helpers.each(this.getDataset().data, function(value) {
130-
this.getDataset().total += Math.abs(value);
131-
}, this);
132-
133127
this.outerRadius = this.chart.outerRadius - (this.chart.radiusLength * this.index);
134128
this.innerRadius = this.outerRadius - this.chart.radiusLength;
135129

@@ -145,21 +139,23 @@ module.exports = function(Chart) {
145139

146140
// If there is NaN data before us, we need to calculate the starting angle correctly.
147141
// We could be way more efficient here, but its unlikely that the polar area chart will have a lot of data
148-
var notNullIndex = 0;
142+
var visibleCount = 0;
143+
var meta = this.getMeta();
149144
for (var i = 0; i < index; ++i) {
150-
if (!isNaN(this.getDataset().data[i])) {
151-
++notNullIndex;
145+
if (!isNaN(this.getDataset().data[i]) && !meta.data[i].hidden) {
146+
++visibleCount;
152147
}
153148
}
154149

155-
var startAngle = (-0.5 * Math.PI) + (circumference * notNullIndex);
156-
var endAngle = startAngle + circumference;
150+
var distance = arc.hidden? 0 : this.chart.scale.getDistanceFromCenterForValue(this.getDataset().data[index]);
151+
var startAngle = (-0.5 * Math.PI) + (circumference * visibleCount);
152+
var endAngle = startAngle + (arc.hidden? 0 : circumference);
157153

158154
var resetModel = {
159155
x: centerX,
160156
y: centerY,
161157
innerRadius: 0,
162-
outerRadius: this.chart.options.animateScale ? 0 : this.chart.scale.getDistanceFromCenterForValue(this.getDataset().data[index]),
158+
outerRadius: this.chart.options.animateScale ? 0 : distance,
163159
startAngle: this.chart.options.animateRotate ? Math.PI * -0.5 : startAngle,
164160
endAngle: this.chart.options.animateRotate ? Math.PI * -0.5 : endAngle,
165161

@@ -182,7 +178,7 @@ module.exports = function(Chart) {
182178
x: centerX,
183179
y: centerY,
184180
innerRadius: 0,
185-
outerRadius: this.chart.scale.getDistanceFromCenterForValue(this.getDataset().data[index]),
181+
outerRadius: distance,
186182
startAngle: startAngle,
187183
endAngle: endAngle,
188184

@@ -225,15 +221,20 @@ module.exports = function(Chart) {
225221
calculateCircumference: function(value) {
226222
if (isNaN(value)) {
227223
return 0;
228-
} else {
229-
// Count the number of NaN values
230-
var numNaN = helpers.where(this.getDataset().data, function(data) {
231-
return isNaN(data);
232-
}).length;
233-
234-
return (2 * Math.PI) / (this.getDataset().data.length - numNaN);
235224
}
225+
226+
// Count the number of "visible"" values
227+
var meta = this.getMeta();
228+
var count = 0;
229+
230+
this.getDataset().data.forEach(function(value, index) {
231+
if (!isNaN(value) && !meta.data[index].hidden) {
232+
count++;
233+
}
234+
});
235+
236+
return (2 * Math.PI) / count;
236237
}
237238
});
238239

239-
};
240+
};

src/core/core.controller.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,6 @@ module.exports = function(Chart) {
416416
data: [],
417417
dataset: null,
418418
controller: null,
419-
hiddenData: {},
420419
hidden: null, // See isDatasetVisible() comment
421420
xAxisID: null,
422421
yAxisID: null

src/core/core.element.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ module.exports = function(Chart) {
1111
this.initialize.apply(this, arguments);
1212
};
1313
helpers.extend(Chart.Element.prototype, {
14-
initialize: function() {},
14+
initialize: function() {
15+
this.hidden = false;
16+
},
1517
pivot: function() {
1618
if (!this._view) {
1719
this._view = helpers.clone(this._model);

src/scales/scale.linear.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,8 @@ module.exports = function(Chart) {
6161

6262
if (this.chart.isDatasetVisible(datasetIndex) && (this.isHorizontal() ? meta.xAxisID === this.id : meta.yAxisID === this.id)) {
6363
helpers.each(dataset.data, function(rawValue, index) {
64-
6564
var value = +this.getRightValue(rawValue);
66-
if (isNaN(value)) {
65+
if (isNaN(value) || meta.data[index].hidden) {
6766
return;
6867
}
6968

@@ -99,7 +98,7 @@ module.exports = function(Chart) {
9998
if (this.chart.isDatasetVisible(datasetIndex) && (this.isHorizontal() ? meta.xAxisID === this.id : meta.yAxisID === this.id)) {
10099
helpers.each(dataset.data, function(rawValue, index) {
101100
var value = +this.getRightValue(rawValue);
102-
if (isNaN(value)) {
101+
if (isNaN(value) || meta.data[index].hidden) {
103102
return;
104103
}
105104

src/scales/scale.logarithmic.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ module.exports = function(Chart) {
4040
helpers.each(dataset.data, function(rawValue, index) {
4141
var values = valuesPerType[meta.type];
4242
var value = +this.getRightValue(rawValue);
43-
if (isNaN(value)) {
43+
if (isNaN(value) || meta.data[index].hidden) {
4444
return;
4545
}
4646

@@ -66,10 +66,10 @@ module.exports = function(Chart) {
6666
} else {
6767
helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {
6868
var meta = this.chart.getDatasetMeta(datasetIndex);
69-
if (this.chart.isDatasetVisible(dataset, datasetIndex) && (this.isHorizontal() ? meta.xAxisID === this.id : meta.yAxisID === this.id)) {
69+
if (this.chart.isDatasetVisible(datasetIndex) && (this.isHorizontal() ? meta.xAxisID === this.id : meta.yAxisID === this.id)) {
7070
helpers.each(dataset.data, function(rawValue, index) {
7171
var value = +this.getRightValue(rawValue);
72-
if (isNaN(value)) {
72+
if (isNaN(value) || meta.data[index].hidden) {
7373
return;
7474
}
7575

src/scales/scale.radialLinear.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,10 @@ module.exports = function(Chart) {
6565

6666
helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {
6767
if (this.chart.isDatasetVisible(datasetIndex)) {
68+
var meta = this.chart.getDatasetMeta(datasetIndex);
6869
helpers.each(dataset.data, function(rawValue, index) {
6970
var value = +this.getRightValue(rawValue);
70-
if (isNaN(value)) {
71+
if (isNaN(value) || meta.data[index].hidden) {
7172
return;
7273
}
7374

0 commit comments

Comments
 (0)