Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Radar Chart Span Gaps #5359

Closed
wants to merge 15 commits into from
Closed
1 change: 1 addition & 0 deletions docs/charts/radar.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ All point* properties can be specified as an array. If these are set to an array
| `pointHoverBorderColor` | `Color/Color[]` | Point border color when hovered.
| `pointHoverBorderWidth` | `Number/Number[]` | Border width of point when hovered.
| `pointHoverRadius` | `Number/Number[]` | The radius of the point when hovered.
| `spanGaps` | `Boolean` | If true, lines will be drawn between points with no or null data. If false, points with `NaN` data will create a break in the line

### pointStyle
The style of point. Options are:
Expand Down
62 changes: 38 additions & 24 deletions src/controllers/controller.radar.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,12 @@ module.exports = function(Chart) {
var me = this;
var meta = me.getMeta();
var line = meta.dataset;
var points = meta.data;
var points = meta.data || [];
var custom = line.custom || {};
var dataset = me.getDataset();
var lineElementOptions = me.chart.options.elements.line;
var scale = me.chart.scale;
var i, ilen;

// Compatibility: If the properties are defined with only the old name, use those values
if ((dataset.tension !== undefined) && (dataset.lineTension === undefined)) {
Expand All @@ -50,6 +51,7 @@ module.exports = function(Chart) {
// Model
_model: {
// Appearance
spanGaps: helpers.valueOrDefault(dataset.spanGaps, me.chart.options.spanGaps),
tension: custom.tension ? custom.tension : helpers.valueOrDefault(dataset.lineTension, lineElementOptions.tension),
backgroundColor: custom.backgroundColor ? custom.backgroundColor : (dataset.backgroundColor || lineElementOptions.backgroundColor),
borderWidth: custom.borderWidth ? custom.borderWidth : (dataset.borderWidth || lineElementOptions.borderWidth),
Expand All @@ -65,12 +67,17 @@ module.exports = function(Chart) {
meta.dataset.pivot();

// Update Points
helpers.each(points, function(point, index) {
me.updateElement(point, index, reset);
}, me);
for (i = 0, ilen = points.length; i < ilen; i++) {
me.updateElement(points[i], i, reset);
}

// Update bezier control points
me.updateBezierControlPoints();

// Now pivot the point for animation
for (i = 0, ilen = points.length; i < ilen; i++) {
points[i].pivot();
}
},
updateElement: function(point, index, reset) {
var me = this;
Expand Down Expand Up @@ -98,6 +105,7 @@ module.exports = function(Chart) {
_model: {
x: reset ? scale.xCenter : pointPosition.x, // value not used in dataset scale, but we want a consistent API between scales
y: reset ? scale.yCenter : pointPosition.y,
skip: custom.skip || isNaN(dataset.data[index]) || dataset.data[index] === null,

// Appearance
tension: custom.tension ? custom.tension : helpers.valueOrDefault(dataset.lineTension, me.chart.options.elements.line.tension),
Expand All @@ -111,32 +119,38 @@ module.exports = function(Chart) {
hitRadius: custom.hitRadius ? custom.hitRadius : helpers.valueAtIndexOrDefault(dataset.pointHitRadius, index, pointElementOptions.hitRadius)
}
});

point._model.skip = custom.skip ? custom.skip : (isNaN(point._model.x) || isNaN(point._model.y));
},
updateBezierControlPoints: function() {
var chartArea = this.chart.chartArea;
var meta = this.getMeta();
var me = this;
var meta = me.getMeta();
var area = me.chart.chartArea;
var points = meta.data || [];
var i, ilen, model, controlPoints;

// Only consider points that are drawn in case the spanGaps option is used
if (meta.dataset._model.spanGaps) {
points = points.filter(function(pt) {
return !pt._model.skip;
});
}

helpers.each(meta.data, function(point, index) {
var model = point._model;
var controlPoints = helpers.splineCurve(
helpers.previousItem(meta.data, index, true)._model,
function capControlPoint(pt, min, max) {
return Math.max(Math.min(pt, max), min);
}

for (i = 0, ilen = points.length; i < ilen; ++i) {
model = points[i]._model;
controlPoints = helpers.splineCurve(
helpers.previousItem(points, i, true)._model,
model,
helpers.nextItem(meta.data, index, true)._model,
helpers.nextItem(points, i, true)._model,
model.tension
);

// Prevent the bezier going outside of the bounds of the graph
model.controlPointPreviousX = Math.max(Math.min(controlPoints.previous.x, chartArea.right), chartArea.left);
model.controlPointPreviousY = Math.max(Math.min(controlPoints.previous.y, chartArea.bottom), chartArea.top);

model.controlPointNextX = Math.max(Math.min(controlPoints.next.x, chartArea.right), chartArea.left);
model.controlPointNextY = Math.max(Math.min(controlPoints.next.y, chartArea.bottom), chartArea.top);

// Now pivot the point for animation
point.pivot();
});
model.controlPointPreviousX = capControlPoint(controlPoints.previous.x, area.left, area.right);
model.controlPointPreviousY = capControlPoint(controlPoints.previous.y, area.top, area.bottom);
model.controlPointNextX = capControlPoint(controlPoints.next.x, area.left, area.right);
model.controlPointNextY = capControlPoint(controlPoints.next.y, area.top, area.bottom);
}
},

setHoverStyle: function(point) {
Expand Down
10 changes: 8 additions & 2 deletions src/elements/element.line.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,15 @@ module.exports = Element.extend({
var lastDrawnIndex = -1;
var index, current, previous, currentVM;

// If we are looping, adding the first point again
// If we are looping, adding the first non-skipped point again
if (me._loop && points.length) {
points.push(points[0]);
for (index = 0; index < points.length; index++) {
current = points[index];
if (!current._view.skip) {
points.push(current);
break;
}
}
}

ctx.save();
Expand Down
8 changes: 7 additions & 1 deletion src/plugins/plugin.filler.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,16 +220,22 @@ function doFill(ctx, points, mapper, view, color, loop) {
var len0 = 0;
var len1 = 0;
var i, ilen, index, p0, p1, d0, d1;
var loopOffset;

ctx.beginPath();

for (i = 0, ilen = (count + !!loop); i < ilen; ++i) {
for (i = 0, ilen = count; i < ilen; ++i) {
index = i % count;
p0 = points[index]._view;
p1 = mapper(p0, index, view);
d0 = isDrawable(p0);
d1 = isDrawable(p1);

if (loop && loopOffset === undefined && d0) {
loopOffset = i + 1;
ilen = count + loopOffset;
}

if (d0 && d1) {
len0 = curve0.push(p0);
len1 = curve1.push(p1);
Expand Down
28 changes: 28 additions & 0 deletions test/fixtures/controller.radar/span-gaps-end-true.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"type": "radar",
"data": {
"labels": ["A", "B", "C", "D", "E"],
"datasets": [{
"label": "Dataset",
"backgroundColor": "#FF6384",
"borderColor": "#FF6384",
"pointBackgroundColor": "#FF6384",
"data": [10, 20, 30, 50, null]
}]
},
"options": {
"spanGaps": true,
"legend": {
"display": false
},
"title": {
"display": false
},
"scale": {
"display": false,
"ticks": {
"beginAtZero": true
}
}
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 28 additions & 0 deletions test/fixtures/controller.radar/span-gaps-middle-false.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"type": "radar",
"data": {
"labels": ["A", "B", "C", "D", "E"],
"datasets": [{
"label": "Dataset",
"backgroundColor": "#FF6384",
"borderColor": "#FF6384",
"pointBackgroundColor": "#FF6384",
"data": [10, 20, 30, null, 40]
}]
},
"options": {
"spanGaps": true,
"legend": {
"display": false
},
"title": {
"display": false
},
"scale": {
"display": false,
"ticks": {
"beginAtZero": true
}
}
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 28 additions & 0 deletions test/fixtures/controller.radar/span-gaps-middle-true.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"type": "radar",
"data": {
"labels": ["A", "B", "C", "D", "E"],
"datasets": [{
"label": "Dataset",
"backgroundColor": "#FF6384",
"borderColor": "#FF6384",
"pointBackgroundColor": "#FF6384",
"data": [10, 20, 30, null, 40]
}]
},
"options": {
"spanGaps": true,
"legend": {
"display": false
},
"title": {
"display": false
},
"scale": {
"display": false,
"ticks": {
"beginAtZero": true
}
}
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 28 additions & 0 deletions test/fixtures/controller.radar/span-gaps-start-true.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"type": "radar",
"data": {
"labels": ["A", "B", "C", "D", "E"],
"datasets": [{
"label": "Dataset",
"backgroundColor": "#FF6384",
"borderColor": "#FF6384",
"pointBackgroundColor": "#FF6384",
"data": [null, 20, 30, 50, 40]
}]
},
"options": {
"spanGaps": true,
"legend": {
"display": false
},
"title": {
"display": false
},
"scale": {
"display": false,
"ticks": {
"beginAtZero": true
}
}
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions test/specs/element.line.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -1879,6 +1879,9 @@ describe('Chart.elements.Line', function() {
}, {
name: 'lineTo',
args: [19, -5]
}, {
name: 'lineTo',
args: [5, 0]
}, {
name: 'stroke',
args: [],
Expand Down