diff --git a/samples/line-skip-points.html b/samples/line-skip-points.html
new file mode 100644
index 000000000..a0a9e6e11
--- /dev/null
+++ b/samples/line-skip-points.html
@@ -0,0 +1,175 @@
+
+
+
+
+ Line Chart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/radar-skip-points.html b/samples/radar-skip-points.html
new file mode 100644
index 000000000..14c5072a5
--- /dev/null
+++ b/samples/radar-skip-points.html
@@ -0,0 +1,152 @@
+
+
+
+
+ Radar Chart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/radar.html b/samples/radar.html
index da45b3e8f..eab9a8655 100644
--- a/samples/radar.html
+++ b/samples/radar.html
@@ -41,7 +41,7 @@
label: "My First dataset",
backgroundColor: "rgba(220,220,220,0.2)",
pointBackgroundColor: "rgba(220,220,220,1)",
- data: [null, randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
+ data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
}, {
label: 'Hidden dataset',
hidden: true,
@@ -52,7 +52,7 @@
pointBackgroundColor: "rgba(151,187,205,1)",
hoverPointBackgroundColor: "#fff",
pointHighlightStroke: "rgba(151,187,205,1)",
- data: [null, randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
+ data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
},]
},
options: {
diff --git a/src/controllers/controller.line.js b/src/controllers/controller.line.js
index 954686e06..2f2ef279d 100644
--- a/src/controllers/controller.line.js
+++ b/src/controllers/controller.line.js
@@ -251,28 +251,12 @@
point._model.tension
);
- point._model.controlPointPreviousX = controlPoints.previous.x;
- point._model.controlPointNextX = controlPoints.next.x;
-
// Prevent the bezier going outside of the bounds of the graph
+ point._model.controlPointPreviousX = Math.max(Math.min(controlPoints.previous.x, this.chart.chartArea.right), this.chart.chartArea.left);
+ point._model.controlPointPreviousY = Math.max(Math.min(controlPoints.previous.y, this.chart.chartArea.bottom), this.chart.chartArea.top);
- // Cap outer bezier handles to the upper/lower scale bounds
- if (controlPoints.next.y > this.chart.chartArea.bottom) {
- point._model.controlPointNextY = this.chart.chartArea.bottom;
- } else if (controlPoints.next.y < this.chart.chartArea.top) {
- point._model.controlPointNextY = this.chart.chartArea.top;
- } else {
- point._model.controlPointNextY = controlPoints.next.y;
- }
-
- // Cap inner bezier handles to the upper/lower scale bounds
- if (controlPoints.previous.y > this.chart.chartArea.bottom) {
- point._model.controlPointPreviousY = this.chart.chartArea.bottom;
- } else if (controlPoints.previous.y < this.chart.chartArea.top) {
- point._model.controlPointPreviousY = this.chart.chartArea.top;
- } else {
- point._model.controlPointPreviousY = controlPoints.previous.y;
- }
+ point._model.controlPointNextX = Math.max(Math.min(controlPoints.next.x, this.chart.chartArea.right), this.chart.chartArea.left);
+ point._model.controlPointNextY = Math.max(Math.min(controlPoints.next.y, this.chart.chartArea.bottom), this.chart.chartArea.top);
// Now pivot the point for animation
point.pivot();
diff --git a/src/controllers/controller.radar.js b/src/controllers/controller.radar.js
index b8bcf1441..639c87722 100644
--- a/src/controllers/controller.radar.js
+++ b/src/controllers/controller.radar.js
@@ -197,28 +197,12 @@
point._model.tension
);
- point._model.controlPointPreviousX = controlPoints.previous.x;
- point._model.controlPointNextX = controlPoints.next.x;
-
// Prevent the bezier going outside of the bounds of the graph
+ point._model.controlPointPreviousX = Math.max(Math.min(controlPoints.previous.x, this.chart.chartArea.right), this.chart.chartArea.left);
+ point._model.controlPointPreviousY = Math.max(Math.min(controlPoints.previous.y, this.chart.chartArea.bottom), this.chart.chartArea.top);
- // Cap outer bezier handles to the upper/lower scale bounds
- if (controlPoints.next.y > this.chart.chartArea.bottom) {
- point._model.controlPointNextY = this.chart.chartArea.bottom;
- } else if (controlPoints.next.y < this.chart.chartArea.top) {
- point._model.controlPointNextY = this.chart.chartArea.top;
- } else {
- point._model.controlPointNextY = controlPoints.next.y;
- }
-
- // Cap inner bezier handles to the upper/lower scale bounds
- if (controlPoints.previous.y > this.chart.chartArea.bottom) {
- point._model.controlPointPreviousY = this.chart.chartArea.bottom;
- } else if (controlPoints.previous.y < this.chart.chartArea.top) {
- point._model.controlPointPreviousY = this.chart.chartArea.top;
- } else {
- point._model.controlPointPreviousY = controlPoints.previous.y;
- }
+ point._model.controlPointNextX = Math.max(Math.min(controlPoints.next.x, this.chart.chartArea.right), this.chart.chartArea.left);
+ point._model.controlPointNextY = Math.max(Math.min(controlPoints.next.y, this.chart.chartArea.bottom), this.chart.chartArea.top);
// Now pivot the point for animation
point.pivot();
diff --git a/src/core/core.element.js b/src/core/core.element.js
index 594269619..d9c0d35a6 100644
--- a/src/core/core.element.js
+++ b/src/core/core.element.js
@@ -38,7 +38,7 @@
// Init if doesn't exist
else if (!this._view[key]) {
- if (typeof value === 'number') {
+ if (typeof value === 'number' && isNaN(this._view[key]) === false) {
this._view[key] = value * ease;
} else {
this._view[key] = value || null;
@@ -61,14 +61,13 @@
}
// Number transitions
else if (typeof value === 'number') {
- var startVal = this._start[key] !== undefined ? this._start[key] : 0;
+ var startVal = this._start[key] !== undefined && isNaN(this._start[key]) === false ? this._start[key] : 0;
this._view[key] = ((this._model[key] - startVal) * ease) + startVal;
}
// Everything else
else {
this._view[key] = value;
}
-
}, this);
if (ease === 1) {
diff --git a/src/core/core.helpers.js b/src/core/core.helpers.js
index 1f19a5c0a..50d5c51ec 100644
--- a/src/core/core.helpers.js
+++ b/src/core/core.helpers.js
@@ -321,27 +321,29 @@
aliasPixel = helpers.aliasPixel = function(pixelWidth) {
return (pixelWidth % 2 === 0) ? 0 : 0.5;
},
- splineCurve = helpers.splineCurve = function(FirstPoint, MiddlePoint, AfterPoint, t) {
+ splineCurve = helpers.splineCurve = function(firstPoint, middlePoint, afterPoint, t) {
//Props to Rob Spencer at scaled innovation for his post on splining between points
//http://scaledinnovation.com/analytics/splines/aboutSplines.html
// This function must also respect "skipped" points
- var previous = FirstPoint,
- current = MiddlePoint,
- next = AfterPoint;
+ var previous = firstPoint.skip ? middlePoint : firstPoint,
+ current = middlePoint,
+ next = afterPoint.skip ? middlePoint : afterPoint;
- if (previous.skip) {
- previous = current;
- }
- if (next.skip) {
- next = current;
- }
+ var d01 = Math.sqrt(Math.pow(current.x - previous.x, 2) + Math.pow(current.y - previous.y, 2));
+ var d12 = Math.sqrt(Math.pow(next.x - current.x, 2) + Math.pow(next.y - current.y, 2));
+
+ var s01 = d01 / (d01 + d12);
+ var s12 = d12 / (d01 + d12);
+
+ // If all points are the same, s01 & s02 will be inf
+ s01 = isNaN(s01) ? 0 : s01;
+ s12 = isNaN(s12) ? 0 : s12;
+
+ var fa = t * s01; // scaling factor for triangle Ta
+ var fb = t * s12;
- var d01 = Math.sqrt(Math.pow(current.x - previous.x, 2) + Math.pow(current.y - previous.y, 2)),
- d12 = Math.sqrt(Math.pow(next.x - current.x, 2) + Math.pow(next.y - current.y, 2)),
- fa = t * d01 / (d01 + d12), // scaling factor for triangle Ta
- fb = t * d12 / (d01 + d12);
return {
previous: {
x: current.x - fa * (next.x - previous.x),
diff --git a/src/elements/element.line.js b/src/elements/element.line.js
index f094dea6e..00ae696cf 100644
--- a/src/elements/element.line.js
+++ b/src/elements/element.line.js
@@ -29,64 +29,38 @@
fill: true, // do we fill in the area between the line and its base axis
};
-
Chart.elements.Line = Chart.Element.extend({
+ lineToNextPoint: function(previousPoint, point, nextPoint, skipHandler, previousSkipHandler) {
+ var ctx = this._chart.ctx;
+
+ if (point._view.skip) {
+ skipHandler.call(this, previousPoint, point, nextPoint);
+ } else if (previousPoint._view.skip) {
+ previousSkipHandler.call(this, previousPoint, point, nextPoint);
+ } else {
+ // Line between points
+ ctx.bezierCurveTo(
+ previousPoint._view.controlPointNextX,
+ previousPoint._view.controlPointNextY,
+ point._view.controlPointPreviousX,
+ point._view.controlPointPreviousY,
+ point._view.x,
+ point._view.y
+ );
+ }
+ },
+
draw: function() {
+ var _this = this;
var vm = this._view;
var ctx = this._chart.ctx;
var first = this._children[0];
var last = this._children[this._children.length - 1];
- ctx.save();
-
- // Draw the background first (so the border is always on top)
- helpers.each(this._children, function(point, index) {
-
- var previous = helpers.previousItem(this._children, index);
- var next = helpers.nextItem(this._children, index);
-
- // First point moves to it's starting position no matter what
- if (!index) {
- ctx.moveTo(point._view.x, vm.scaleZero);
- }
-
- // Skip this point, draw to scaleZero, move to next point, and draw to next point
- if (point._view.skip && !this.loop) {
- ctx.lineTo(previous._view.x, vm.scaleZero);
- ctx.moveTo(next._view.x, vm.scaleZero);
- return;
- }
-
- // The previous line was skipped, so just draw a normal straight line to the point
- if (previous._view.skip) {
- ctx.lineTo(point._view.x, point._view.y);
- return;
- }
-
- // Draw a bezier to point
- if (vm.tension > 0 && index) {
- //ctx.lineTo(point._view.x, point._view.y);
- ctx.bezierCurveTo(
- previous._view.controlPointNextX,
- previous._view.controlPointNextY,
- point._view.controlPointPreviousX,
- point._view.controlPointPreviousY,
- point._view.x,
- point._view.y
- );
- return;
- }
-
- // Draw a straight line to the point
- ctx.lineTo(point._view.x, point._view.y);
-
- }, this);
-
- // For radial scales, loop back around to the first point
- if (this._loop) {
- // Draw a bezier line
- if (vm.tension > 0 && !first._view.skip) {
+ function loopBackToStart(drawLineToCenter) {
+ if (!first._view.skip && !last._view.skip) {
+ // Draw a bezier line from last to first
ctx.bezierCurveTo(
last._view.controlPointNextX,
last._view.controlPointNextY,
@@ -95,23 +69,68 @@
first._view.x,
first._view.y
);
- return;
+ } else if (drawLineToCenter) {
+ // Go to center
+ ctx.lineTo(_this._view.scaleZero.x, _this._view.scaleZero.y);
}
- // Draw a straight line
- ctx.lineTo(first._view.x, first._view.y);
}
+ ctx.save();
+
// If we had points and want to fill this line, do so.
if (this._children.length > 0 && vm.fill) {
- //Round off the line by going to the base of the chart, back to the start, then fill.
- ctx.lineTo(this._children[this._children.length - 1]._view.x, vm.scaleZero);
- ctx.lineTo(this._children[0]._view.x, vm.scaleZero);
+ // Draw the background first (so the border is always on top)
+ ctx.beginPath();
+
+ helpers.each(this._children, function(point, index) {
+ var previous = helpers.previousItem(this._children, index);
+ var next = helpers.nextItem(this._children, index);
+
+ // First point moves to it's starting position no matter what
+ if (index === 0) {
+ if (this._loop) {
+ ctx.moveTo(vm.scaleZero.x, vm.scaleZero.y);
+ } else {
+ ctx.moveTo(point._view.x, vm.scaleZero);
+ }
+
+ if (point._view.skip) {
+ if (!this._loop) {
+ ctx.moveTo(next._view.x, this._view.scaleZero);
+ }
+ } else {
+ ctx.lineTo(point._view.x, point._view.y);
+ }
+ } else {
+ this.lineToNextPoint(previous, point, next, function(previousPoint, point, nextPoint) {
+ if (this._loop) {
+ // Go to center
+ ctx.lineTo(this._view.scaleZero.x, this._view.scaleZero.y);
+ } else {
+ ctx.lineTo(previousPoint._view.x, this._view.scaleZero);
+ ctx.moveTo(nextPoint._view.x, this._view.scaleZero);
+ }
+ }, function(previousPoint, point, nextPoint) {
+ // If we skipped the last point, draw a line to ourselves so that the fill is nice
+ ctx.lineTo(point._view.x, point._view.y);
+ });
+ }
+ }, this);
+
+ // For radial scales, loop back around to the first point
+ if (this._loop) {
+ loopBackToStart(true);
+ } else {
+ //Round off the line by going to the base of the chart, back to the start, then fill.
+ ctx.lineTo(this._children[this._children.length - 1]._view.x, vm.scaleZero);
+ ctx.lineTo(this._children[0]._view.x, vm.scaleZero);
+ }
+
ctx.fillStyle = vm.backgroundColor || Chart.defaults.global.defaultColor;
ctx.closePath();
ctx.fill();
}
-
// Now draw the line between all the points with any borders
ctx.lineCap = vm.borderCapStyle || Chart.defaults.global.elements.line.borderCapStyle;
@@ -130,62 +149,20 @@
var previous = helpers.previousItem(this._children, index);
var next = helpers.nextItem(this._children, index);
- if (!index) {
- ctx.moveTo(point._view.x, vm.scaleZero);
- }
-
- // Skip this point and move to the next points zeroPoint
- if (point._view.skip && !this.loop) {
- ctx.moveTo(next._view.x, vm.scaleZero);
- return;
- }
-
- // Previous point was skipped, just move to the point
- if (previous._view.skip) {
+ if (index === 0) {
ctx.moveTo(point._view.x, point._view.y);
- return;
+ } else {
+ this.lineToNextPoint(previous, point, next, function(previousPoint, point, nextPoint) {
+ ctx.moveTo(nextPoint._view.x, nextPoint._view.y);
+ }, function(previousPoint, point, nextPoint) {
+ // If we skipped the last point, move up to our point preventing a line from being drawn
+ ctx.moveTo(point._view.x, point._view.y);
+ });
}
-
- // If First point, move to the point ahead of time (so a line doesn't get drawn up the left axis)
- if (!index) {
- ctx.moveTo(point._view.x, point._view.y);
- }
-
- // Draw a bezier line to the point
- if (vm.tension > 0 && index) {
- ctx.bezierCurveTo(
- previous._view.controlPointNextX,
- previous._view.controlPointNextY,
- point._view.controlPointPreviousX,
- point._view.controlPointPreviousY,
- point._view.x,
- point._view.y
- );
- return;
- }
-
- // Draw a straight line to the point
- ctx.lineTo(point._view.x, point._view.y);
-
}, this);
- if (this._loop && !first._view.skip) {
-
- // Draw a bezier line to the first point
- if (vm.tension > 0) {
- ctx.bezierCurveTo(
- last._view.controlPointNextX,
- last._view.controlPointNextY,
- first._view.controlPointPreviousX,
- first._view.controlPointPreviousY,
- first._view.x,
- first._view.y
- );
- return;
- }
-
- // Draw a straight line to the first point
- ctx.lineTo(first._view.x, first._view.y);
+ if (this._loop) {
+ loopBackToStart();
}
ctx.stroke();
diff --git a/src/scales/scale.radialLinear.js b/src/scales/scale.radialLinear.js
index 15fdb3626..19f310ec2 100644
--- a/src/scales/scale.radialLinear.js
+++ b/src/scales/scale.radialLinear.js
@@ -272,7 +272,10 @@
return index * angleMultiplier - (Math.PI / 2);
},
getDistanceFromCenterForValue: function(value) {
- if (value === null) return 0; // null always in center
+ if (value === null) {
+ return 0; // null always in center
+ }
+
// Take into account half font size + the yPadding of the top value
var scalingFactor = this.drawingArea / (this.max - this.min);
if (this.options.reverse) {
diff --git a/test/controller.line.tests.js b/test/controller.line.tests.js
index cdfb9bdc9..b8e8695e2 100644
--- a/test/controller.line.tests.js
+++ b/test/controller.line.tests.js
@@ -192,7 +192,7 @@ describe('Line controller tests', function() {
chartArea: {
bottom: 200,
left: xScale.left,
- right: 200,
+ right: xScale.left + 200,
top: 0
},
data: data,
diff --git a/test/element.line.tests.js b/test/element.line.tests.js
index 2b4028fbe..926345feb 100644
--- a/test/element.line.tests.js
+++ b/test/element.line.tests.js
@@ -22,6 +22,8 @@ describe('Line element tests', function() {
_view: {
x: 0,
y: 10,
+ controlPointNextX: 0,
+ controlPointNextY: 10
}
}));
points.push(new Chart.elements.Point({
@@ -30,6 +32,10 @@ describe('Line element tests', function() {
_view: {
x: 5,
y: 0,
+ controlPointPreviousX: 5,
+ controlPointPreviousY: 0,
+ controlPointNextX: 5,
+ controlPointNextY: 0
}
}));
points.push(new Chart.elements.Point({
@@ -38,6 +44,10 @@ describe('Line element tests', function() {
_view: {
x: 15,
y: -10,
+ controlPointPreviousX: 15,
+ controlPointPreviousY: -10,
+ controlPointNextX: 15,
+ controlPointNextY: -10
}
}));
points.push(new Chart.elements.Point({
@@ -46,6 +56,10 @@ describe('Line element tests', function() {
_view: {
x: 19,
y: -5,
+ controlPointPreviousX: 19,
+ controlPointPreviousY: -5,
+ controlPointNextX: 19,
+ controlPointNextY: -5
}
}));
@@ -68,21 +82,6 @@ describe('Line element tests', function() {
expect(mockContext.getCalls()).toEqual([{
name: 'save',
args: [],
- }, {
- name: 'moveTo',
- args: [0, 0]
- }, {
- name: 'lineTo',
- args: [0, 10]
- }, {
- name: 'lineTo',
- args: [5, 0]
- }, {
- name: 'lineTo',
- args: [15, -10]
- }, {
- name: 'lineTo',
- args: [19, -5]
}, {
name: 'setLineCap',
args: ['butt']
@@ -106,24 +105,18 @@ describe('Line element tests', function() {
}, {
name: 'beginPath',
args: []
- }, {
- name: 'moveTo',
- args: [0, 0]
}, {
name: 'moveTo',
args: [0, 10]
}, {
- name: 'lineTo',
- args: [0, 10]
+ name: 'bezierCurveTo',
+ args: [0, 10, 5, 0, 5, 0]
}, {
- name: 'lineTo',
- args: [5, 0]
+ name: 'bezierCurveTo',
+ args: [5, 0, 15, -10, 15, -10]
}, {
- name: 'lineTo',
- args: [15, -10]
- }, {
- name: 'lineTo',
- args: [19, -5]
+ name: 'bezierCurveTo',
+ args: [15, -10, 19, -5, 19, -5]
}, {
name: 'stroke',
args: [],
@@ -143,7 +136,9 @@ describe('Line element tests', function() {
_index: 0,
_view: {
x: 0,
- y: 10
+ y: 10,
+ controlPointNextX: 0,
+ controlPointNextY: 10
}
}));
points.push(new Chart.elements.Point({
@@ -151,7 +146,11 @@ describe('Line element tests', function() {
_index: 1,
_view: {
x: 5,
- y: 0
+ y: 0,
+ controlPointPreviousX: 5,
+ controlPointPreviousY: 0,
+ controlPointNextX: 5,
+ controlPointNextY: 0
}
}));
points.push(new Chart.elements.Point({
@@ -159,7 +158,11 @@ describe('Line element tests', function() {
_index: 2,
_view: {
x: 15,
- y: -10
+ y: -10,
+ controlPointPreviousX: 15,
+ controlPointPreviousY: -10,
+ controlPointNextX: 15,
+ controlPointNextY: -10
}
}));
points.push(new Chart.elements.Point({
@@ -167,7 +170,11 @@ describe('Line element tests', function() {
_index: 3,
_view: {
x: 19,
- y: -5
+ y: -5,
+ controlPointPreviousX: 19,
+ controlPointPreviousY: -5,
+ controlPointNextX: 19,
+ controlPointNextY: -5
}
}));
@@ -198,6 +205,9 @@ describe('Line element tests', function() {
var expected = [{
name: 'save',
args: [],
+ }, {
+ name: 'beginPath',
+ args: []
}, {
name: 'moveTo',
args: [0, 2]
@@ -205,14 +215,14 @@ describe('Line element tests', function() {
name: 'lineTo',
args: [0, 10]
}, {
- name: 'lineTo',
- args: [5, 0]
+ name: 'bezierCurveTo',
+ args: [0, 10, 5, 0, 5, 0]
}, {
- name: 'lineTo',
- args: [15, -10]
+ name: 'bezierCurveTo',
+ args: [5, 0, 15, -10, 15, -10]
}, {
- name: 'lineTo',
- args: [19, -5]
+ name: 'bezierCurveTo',
+ args: [15, -10, 19, -5, 19, -5]
}, {
name: 'lineTo',
args: [19, 2]
@@ -251,24 +261,171 @@ describe('Line element tests', function() {
}, {
name: 'beginPath',
args: []
+ }, {
+ name: 'moveTo',
+ args: [0, 10]
+ }, {
+ name: 'bezierCurveTo',
+ args: [0, 10, 5, 0, 5, 0]
+ }, {
+ name: 'bezierCurveTo',
+ args: [5, 0, 15, -10, 15, -10]
+ }, {
+ name: 'bezierCurveTo',
+ args: [15, -10, 19, -5, 19, -5]
+ }, {
+ name: 'stroke',
+ args: [],
+ }, {
+ name: 'restore',
+ args: []
+ }];
+ expect(mockContext.getCalls()).toEqual(expected);
+ });
+
+ it ('should skip points correctly', function() {
+ var mockContext = window.createMockContext();
+
+ // Create our points
+ var points = [];
+ points.push(new Chart.elements.Point({
+ _datasetindex: 2,
+ _index: 0,
+ _view: {
+ x: 0,
+ y: 10,
+ controlPointNextX: 0,
+ controlPointNextY: 10
+ }
+ }));
+ points.push(new Chart.elements.Point({
+ _datasetindex: 2,
+ _index: 1,
+ _view: {
+ x: 5,
+ y: 0,
+ controlPointPreviousX: 5,
+ controlPointPreviousY: 0,
+ controlPointNextX: 5,
+ controlPointNextY: 0
+ }
+ }));
+ points.push(new Chart.elements.Point({
+ _datasetindex: 2,
+ _index: 2,
+ _view: {
+ x: 15,
+ y: -10,
+ controlPointPreviousX: 15,
+ controlPointPreviousY: -10,
+ controlPointNextX: 15,
+ controlPointNextY: -10,
+ skip: true
+ }
+ }));
+ points.push(new Chart.elements.Point({
+ _datasetindex: 2,
+ _index: 3,
+ _view: {
+ x: 19,
+ y: -5,
+ controlPointPreviousX: 19,
+ controlPointPreviousY: -5,
+ controlPointNextX: 19,
+ controlPointNextY: -5
+ }
+ }));
+
+ var line = new Chart.elements.Line({
+ _datasetindex: 2,
+ _chart: {
+ ctx: mockContext,
+ },
+ _children: points,
+ // Need to provide some settings
+ _view: {
+ fill: true,
+ scaleZero: 2, // for filling lines
+ tension: 0.0, // no bezier curve for now
+ }
+ });
+
+ line.draw();
+
+ var expected = [{
+ name: 'save',
+ args: []
+ }, {
+ name: 'beginPath',
+ args: []
}, {
name: 'moveTo',
args: [0, 2]
+ }, {
+ name: 'lineTo',
+ args: [0, 10]
+ }, {
+ name: 'bezierCurveTo',
+ args: [0, 10, 5, 0, 5, 0]
+ }, {
+ name: 'lineTo',
+ args: [5, 2]
+ }, {
+ name: 'moveTo',
+ args: [19, 2]
+ }, {
+ name: 'lineTo',
+ args: [19, -5]
+ }, {
+ name: 'lineTo',
+ args: [19, 2]
+ }, {
+ name: 'lineTo',
+ args: [0, 2]
+ }, {
+ name: 'setFillStyle',
+ args: ['rgba(0,0,0,0.1)']
+ }, {
+ name: 'closePath',
+ args: []
+ }, {
+ name: 'fill',
+ args: []
+ }, {
+ name: 'setLineCap',
+ args: ['butt']
+ }, {
+ name: 'setLineDash',
+ args: [
+ []
+ ]
+ }, {
+ name: 'setLineDashOffset',
+ args: [0.0]
+ }, {
+ name: 'setLineJoin',
+ args: ['miter']
+ }, {
+ name: 'setLineWidth',
+ args: [3]
+ }, {
+ name: 'setStrokeStyle',
+ args: ['rgba(0,0,0,0.1)']
+ }, {
+ name: 'beginPath',
+ args: []
}, {
name: 'moveTo',
args: [0, 10]
}, {
- name: 'lineTo',
- args: [0, 10]
+ name: 'bezierCurveTo',
+ args: [0, 10, 5, 0, 5, 0]
}, {
- name: 'lineTo',
- args: [5, 0]
+ name: 'moveTo',
+ args: [19, -5]
}, {
- name: 'lineTo',
- args: [15, -10]
- }, {
- name: 'lineTo',
- args: [19, -5]
+ name: 'moveTo',
+ args: [19, -5]
}, {
name: 'stroke',
args: [],
@@ -289,7 +446,11 @@ describe('Line element tests', function() {
_index: 0,
_view: {
x: 0,
- y: 10
+ y: 10,
+ controlPointPreviousX: 0,
+ controlPointPreviousY: 10,
+ controlPointNextX: 0,
+ controlPointNextY: 10
}
}));
points.push(new Chart.elements.Point({
@@ -297,7 +458,11 @@ describe('Line element tests', function() {
_index: 1,
_view: {
x: 5,
- y: 0
+ y: 0,
+ controlPointPreviousX: 5,
+ controlPointPreviousY: 0,
+ controlPointNextX: 5,
+ controlPointNextY: 0
}
}));
points.push(new Chart.elements.Point({
@@ -305,7 +470,11 @@ describe('Line element tests', function() {
_index: 2,
_view: {
x: 15,
- y: -10
+ y: -10,
+ controlPointPreviousX: 15,
+ controlPointPreviousY: -10,
+ controlPointNextX: 15,
+ controlPointNextY: -10
}
}));
points.push(new Chart.elements.Point({
@@ -313,7 +482,11 @@ describe('Line element tests', function() {
_index: 3,
_view: {
x: 19,
- y: -5
+ y: -5,
+ controlPointPreviousX: 19,
+ controlPointPreviousY: -5,
+ controlPointNextX: 19,
+ controlPointNextY: -5
}
}));
@@ -326,9 +499,12 @@ describe('Line element tests', function() {
_loop: true, // want the line to loop back to the first point
// Need to provide some settings
_view: {
- fill: false, // don't want to fill
+ fill: true, // don't want to fill
tension: 0.0, // no bezier curve for now
- scaleZero: 0,
+ scaleZero: {
+ x: 3,
+ y: 2
+ },
}
});
@@ -337,24 +513,36 @@ describe('Line element tests', function() {
expect(mockContext.getCalls()).toEqual([{
name: 'save',
args: [],
+ }, {
+ name: 'beginPath',
+ args: []
}, {
name: 'moveTo',
- args: [0, 0]
+ args: [3, 2]
}, {
name: 'lineTo',
args: [0, 10]
}, {
- name: 'lineTo',
- args: [5, 0]
+ name: 'bezierCurveTo',
+ args: [0, 10, 5, 0, 5, 0]
}, {
- name: 'lineTo',
- args: [15, -10]
+ name: 'bezierCurveTo',
+ args: [5, 0, 15, -10, 15, -10]
}, {
- name: 'lineTo',
- args: [19, -5]
+ name: 'bezierCurveTo',
+ args: [15, -10, 19, -5, 19, -5]
}, {
- name: 'lineTo',
- args: [0, 10]
+ name: 'bezierCurveTo',
+ args: [19, -5, 0, 10, 0, 10]
+ }, {
+ name: 'setFillStyle',
+ args: ['rgba(0,0,0,0.1)']
+ }, {
+ name: 'closePath',
+ args: []
+ }, {
+ name: 'fill',
+ args: []
}, {
name: 'setLineCap',
args: ['butt']
@@ -378,27 +566,21 @@ describe('Line element tests', function() {
}, {
name: 'beginPath',
args: []
- }, {
- name: 'moveTo',
- args: [0, 0]
}, {
name: 'moveTo',
args: [0, 10]
}, {
- name: 'lineTo',
- args: [0, 10]
+ name: 'bezierCurveTo',
+ args: [0, 10, 5, 0, 5, 0]
}, {
- name: 'lineTo',
- args: [5, 0]
+ name: 'bezierCurveTo',
+ args: [5, 0, 15, -10, 15, -10]
}, {
- name: 'lineTo',
- args: [15, -10]
+ name: 'bezierCurveTo',
+ args: [15, -10, 19, -5, 19, -5]
}, {
- name: 'lineTo',
- args: [19, -5]
- }, {
- name: 'lineTo',
- args: [0, 10]
+ name: 'bezierCurveTo',
+ args: [19, -5, 0, 10, 0, 10]
}, {
name: 'stroke',
args: [],
@@ -408,7 +590,7 @@ describe('Line element tests', function() {
}]);
});
- it('should draw with bezier curves if tension > 0', function() {
+ it('should be able to draw with a loop back to the beginning point when there is a skip in the middle of the dataset', function() {
var mockContext = window.createMockContext();
// Create our points
@@ -419,10 +601,10 @@ describe('Line element tests', function() {
_view: {
x: 0,
y: 10,
- controlPointNextX: 1,
- controlPointNextY: 1,
controlPointPreviousX: 0,
- controlPointPreviousY: 0,
+ controlPointPreviousY: 10,
+ controlPointNextX: 0,
+ controlPointNextY: 10
}
}));
points.push(new Chart.elements.Point({
@@ -431,10 +613,11 @@ describe('Line element tests', function() {
_view: {
x: 5,
y: 0,
- controlPointNextX: 6,
- controlPointNextY: 7,
- controlPointPreviousX: 4,
- controlPointPreviousY: 3,
+ controlPointPreviousX: 5,
+ controlPointPreviousY: 0,
+ controlPointNextX: 5,
+ controlPointNextY: 0,
+ skip: true
}
}));
points.push(new Chart.elements.Point({
@@ -443,10 +626,10 @@ describe('Line element tests', function() {
_view: {
x: 15,
y: -10,
- controlPointNextX: 16,
- controlPointNextY: 17,
- controlPointPreviousX: 14,
- controlPointPreviousY: 13,
+ controlPointPreviousX: 15,
+ controlPointPreviousY: -10,
+ controlPointNextX: 15,
+ controlPointNextY: -10
}
}));
points.push(new Chart.elements.Point({
@@ -455,10 +638,10 @@ describe('Line element tests', function() {
_view: {
x: 19,
y: -5,
- controlPointNextX: 20,
- controlPointNextY: 21,
- controlPointPreviousX: 18,
- controlPointPreviousY: 17,
+ controlPointPreviousX: 19,
+ controlPointPreviousY: -5,
+ controlPointNextX: 19,
+ controlPointNextY: -5
}
}));
@@ -468,51 +651,47 @@ describe('Line element tests', function() {
ctx: mockContext,
},
_children: points,
+ _loop: true, // want the line to loop back to the first point
// Need to provide some settings
_view: {
- fill: true,
- scaleZero: 2, // for filling lines
- tension: 0.5, // have bezier curves
-
- borderCapStyle: 'round',
- borderColor: 'rgb(255, 255, 0)',
- borderDash: [2, 2],
- borderDashOffset: 1.5,
- borderJoinStyle: 'bevel',
- borderWidth: 4,
- backgroundColor: 'rgb(0, 0, 0)'
+ fill: true, // don't want to fill
+ tension: 0.0, // no bezier curve for now
+ scaleZero: {
+ x: 3,
+ y: 2
+ },
}
});
line.draw();
- var expected = [{
+ expect(mockContext.getCalls()).toEqual([{
name: 'save',
args: [],
+ }, {
+ name: 'beginPath',
+ args: []
}, {
name: 'moveTo',
- args: [0, 2]
+ args: [3, 2]
}, {
name: 'lineTo',
args: [0, 10]
}, {
- name: 'bezierCurveTo',
- args: [1, 1, 4, 3, 5, 0]
- }, {
- name: 'bezierCurveTo',
- args: [6, 7, 14, 13, 15, -10]
- }, {
- name: 'bezierCurveTo',
- args: [16, 17, 18, 17, 19, -5]
+ name: 'lineTo',
+ args: [3, 2]
}, {
name: 'lineTo',
- args: [19, 2]
+ args: [15, -10]
}, {
- name: 'lineTo',
- args: [0, 2]
+ name: 'bezierCurveTo',
+ args: [15, -10, 19, -5, 19, -5]
+ }, {
+ name: 'bezierCurveTo',
+ args: [19, -5, 0, 10, 0, 10]
}, {
name: 'setFillStyle',
- args: ['rgb(0, 0, 0)']
+ args: ['rgba(0,0,0,0.1)']
}, {
name: 'closePath',
args: []
@@ -521,52 +700,349 @@ describe('Line element tests', function() {
args: []
}, {
name: 'setLineCap',
- args: ['round']
+ args: ['butt']
}, {
name: 'setLineDash',
args: [
- [2, 2]
+ []
]
}, {
name: 'setLineDashOffset',
- args: [1.5]
+ args: [0.0]
}, {
name: 'setLineJoin',
- args: ['bevel']
+ args: ['miter']
}, {
name: 'setLineWidth',
- args: [4]
+ args: [3]
}, {
name: 'setStrokeStyle',
- args: ['rgb(255, 255, 0)']
+ args: ['rgba(0,0,0,0.1)']
}, {
name: 'beginPath',
args: []
}, {
name: 'moveTo',
- args: [0, 2]
+ args: [0, 10]
}, {
name: 'moveTo',
- args: [0, 10]
+ args: [15, -10]
}, {
- name: 'lineTo',
- args: [0, 10]
+ name: 'moveTo',
+ args: [15, -10]
}, {
name: 'bezierCurveTo',
- args: [1, 1, 4, 3, 5, 0]
+ args: [15, -10, 19, -5, 19, -5]
}, {
name: 'bezierCurveTo',
- args: [6, 7, 14, 13, 15, -10]
- }, {
- name: 'bezierCurveTo',
- args: [16, 17, 18, 17, 19, -5]
+ args: [19, -5, 0, 10, 0, 10]
}, {
name: 'stroke',
args: [],
}, {
name: 'restore',
args: []
- }];
- expect(mockContext.getCalls()).toEqual(expected);
+ }]);
+ });
+
+ it('should be able to draw with a loop back to the beginning point when the first point is skipped', function() {
+ var mockContext = window.createMockContext();
+
+ // Create our points
+ var points = [];
+ points.push(new Chart.elements.Point({
+ _datasetindex: 2,
+ _index: 0,
+ _view: {
+ x: 0,
+ y: 10,
+ controlPointPreviousX: 0,
+ controlPointPreviousY: 10,
+ controlPointNextX: 0,
+ controlPointNextY: 10,
+ skip: true
+ }
+ }));
+ points.push(new Chart.elements.Point({
+ _datasetindex: 2,
+ _index: 1,
+ _view: {
+ x: 5,
+ y: 0,
+ controlPointPreviousX: 5,
+ controlPointPreviousY: 0,
+ controlPointNextX: 5,
+ controlPointNextY: 0,
+ }
+ }));
+ points.push(new Chart.elements.Point({
+ _datasetindex: 2,
+ _index: 2,
+ _view: {
+ x: 15,
+ y: -10,
+ controlPointPreviousX: 15,
+ controlPointPreviousY: -10,
+ controlPointNextX: 15,
+ controlPointNextY: -10
+ }
+ }));
+ points.push(new Chart.elements.Point({
+ _datasetindex: 2,
+ _index: 3,
+ _view: {
+ x: 19,
+ y: -5,
+ controlPointPreviousX: 19,
+ controlPointPreviousY: -5,
+ controlPointNextX: 19,
+ controlPointNextY: -5
+ }
+ }));
+
+ var line = new Chart.elements.Line({
+ _datasetindex: 2,
+ _chart: {
+ ctx: mockContext,
+ },
+ _children: points,
+ _loop: true, // want the line to loop back to the first point
+ // Need to provide some settings
+ _view: {
+ fill: true, // don't want to fill
+ tension: 0.0, // no bezier curve for now
+ scaleZero: {
+ x: 3,
+ y: 2
+ },
+ }
+ });
+
+ line.draw();
+
+ expect(mockContext.getCalls()).toEqual([{
+ name: 'save',
+ args: [],
+ }, {
+ name: 'beginPath',
+ args: []
+ }, {
+ name: 'moveTo',
+ args: [3, 2]
+ }, {
+ name: 'lineTo',
+ args: [5, 0]
+ }, {
+ name: 'bezierCurveTo',
+ args: [5, 0, 15, -10, 15, -10]
+ }, {
+ name: 'bezierCurveTo',
+ args: [15, -10, 19, -5, 19, -5]
+ }, {
+ name: 'lineTo',
+ args: [3, 2]
+ }, {
+ name: 'setFillStyle',
+ args: ['rgba(0,0,0,0.1)']
+ }, {
+ name: 'closePath',
+ args: []
+ }, {
+ name: 'fill',
+ args: []
+ }, {
+ name: 'setLineCap',
+ args: ['butt']
+ }, {
+ name: 'setLineDash',
+ args: [
+ []
+ ]
+ }, {
+ name: 'setLineDashOffset',
+ args: [0.0]
+ }, {
+ name: 'setLineJoin',
+ args: ['miter']
+ }, {
+ name: 'setLineWidth',
+ args: [3]
+ }, {
+ name: 'setStrokeStyle',
+ args: ['rgba(0,0,0,0.1)']
+ }, {
+ name: 'beginPath',
+ args: []
+ }, {
+ name: 'moveTo',
+ args: [0, 10]
+ }, {
+ name: 'moveTo',
+ args: [5, 0]
+ }, {
+ name: 'bezierCurveTo',
+ args: [5, 0, 15, -10, 15, -10]
+ }, {
+ name: 'bezierCurveTo',
+ args: [15, -10, 19, -5, 19, -5]
+ }, {
+ name: 'stroke',
+ args: [],
+ }, {
+ name: 'restore',
+ args: []
+ }]);
+ });
+
+ it('should be able to draw with a loop back to the beginning point when the last point is skipped', function() {
+ var mockContext = window.createMockContext();
+
+ // Create our points
+ var points = [];
+ points.push(new Chart.elements.Point({
+ _datasetindex: 2,
+ _index: 0,
+ _view: {
+ x: 0,
+ y: 10,
+ controlPointPreviousX: 0,
+ controlPointPreviousY: 10,
+ controlPointNextX: 0,
+ controlPointNextY: 10
+ }
+ }));
+ points.push(new Chart.elements.Point({
+ _datasetindex: 2,
+ _index: 1,
+ _view: {
+ x: 5,
+ y: 0,
+ controlPointPreviousX: 5,
+ controlPointPreviousY: 0,
+ controlPointNextX: 5,
+ controlPointNextY: 0,
+ }
+ }));
+ points.push(new Chart.elements.Point({
+ _datasetindex: 2,
+ _index: 2,
+ _view: {
+ x: 15,
+ y: -10,
+ controlPointPreviousX: 15,
+ controlPointPreviousY: -10,
+ controlPointNextX: 15,
+ controlPointNextY: -10
+ }
+ }));
+ points.push(new Chart.elements.Point({
+ _datasetindex: 2,
+ _index: 3,
+ _view: {
+ x: 19,
+ y: -5,
+ controlPointPreviousX: 19,
+ controlPointPreviousY: -5,
+ controlPointNextX: 19,
+ controlPointNextY: -5,
+ skip: true
+ }
+ }));
+
+ var line = new Chart.elements.Line({
+ _datasetindex: 2,
+ _chart: {
+ ctx: mockContext,
+ },
+ _children: points,
+ _loop: true, // want the line to loop back to the first point
+ // Need to provide some settings
+ _view: {
+ fill: true, // don't want to fill
+ tension: 0.0, // no bezier curve for now
+ scaleZero: {
+ x: 3,
+ y: 2
+ },
+ }
+ });
+
+ line.draw();
+
+ expect(mockContext.getCalls()).toEqual([{
+ name: 'save',
+ args: [],
+ }, {
+ name: 'beginPath',
+ args: []
+ }, {
+ name: 'moveTo',
+ args: [3, 2]
+ }, {
+ name: 'lineTo',
+ args: [0, 10]
+ }, {
+ name: 'bezierCurveTo',
+ args: [0, 10, 5, 0, 5, 0]
+ }, {
+ name: 'bezierCurveTo',
+ args: [5, 0, 15, -10, 15, -10]
+ }, {
+ name: 'lineTo',
+ args: [3, 2]
+ }, {
+ name: 'lineTo',
+ args: [3, 2]
+ }, {
+ name: 'setFillStyle',
+ args: ['rgba(0,0,0,0.1)']
+ }, {
+ name: 'closePath',
+ args: []
+ }, {
+ name: 'fill',
+ args: []
+ }, {
+ name: 'setLineCap',
+ args: ['butt']
+ }, {
+ name: 'setLineDash',
+ args: [
+ []
+ ]
+ }, {
+ name: 'setLineDashOffset',
+ args: [0.0]
+ }, {
+ name: 'setLineJoin',
+ args: ['miter']
+ }, {
+ name: 'setLineWidth',
+ args: [3]
+ }, {
+ name: 'setStrokeStyle',
+ args: ['rgba(0,0,0,0.1)']
+ }, {
+ name: 'beginPath',
+ args: []
+ }, {
+ name: 'moveTo',
+ args: [0, 10]
+ }, {
+ name: 'bezierCurveTo',
+ args: [0, 10, 5, 0, 5, 0]
+ }, {
+ name: 'bezierCurveTo',
+ args: [5, 0, 15, -10, 15, -10]
+ }, {
+ name: 'moveTo',
+ args: [19, -5]
+ }, {
+ name: 'stroke',
+ args: [],
+ }, {
+ name: 'restore',
+ args: []
+ }]);
});
});