From: Evert Timberg Date: Sun, 15 Nov 2015 16:16:41 +0000 (-0500) Subject: Can now skip in all cases (start, mid, end) whether or not there is a look X-Git-Tag: 2.0.0-beta1~25^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0495e45ff7767092fe9a61c79b5c0e49f69a7d0f;p=thirdparty%2FChart.js.git Can now skip in all cases (start, mid, end) whether or not there is a look --- diff --git a/src/elements/element.line.js b/src/elements/element.line.js index dc1f1d635..00ae696cf 100644 --- a/src/elements/element.line.js +++ b/src/elements/element.line.js @@ -29,7 +29,6 @@ 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; @@ -59,8 +58,8 @@ var first = this._children[0]; var last = this._children[this._children.length - 1]; - function loopBackToStart() { - if (!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, @@ -70,7 +69,7 @@ first._view.x, first._view.y ); - } else { + } else if (drawLineToCenter) { // Go to center ctx.lineTo(_this._view.scaleZero.x, _this._view.scaleZero.y); } @@ -84,16 +83,27 @@ ctx.beginPath(); helpers.each(this._children, function(point, index) { - var previous = helpers.previousItem(this._children, index/*, this._loop*/); - var next = helpers.nextItem(this._children, index/*, this._loop*/); + 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) { - ctx.moveTo(point._view.x, vm.scaleZero); - ctx.lineTo(point._view.x, point._view.y); + 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) { + if (this._loop) { // Go to center ctx.lineTo(this._view.scaleZero.x, this._view.scaleZero.y); } else { @@ -109,7 +119,7 @@ // For radial scales, loop back around to the first point if (this._loop) { - loopBackToStart(); + 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); @@ -143,7 +153,7 @@ ctx.moveTo(point._view.x, point._view.y); } else { this.lineToNextPoint(previous, point, next, function(previousPoint, point, nextPoint) { - ctx.moveTo(nextPoint._view.x, this._view.scaleZero); + 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); diff --git a/test/element.line.tests.js b/test/element.line.tests.js index a31077232..926345feb 100644 --- a/test/element.line.tests.js +++ b/test/element.line.tests.js @@ -283,6 +283,159 @@ describe('Line element tests', function() { 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: 'bezierCurveTo', + args: [0, 10, 5, 0, 5, 0] + }, { + name: 'moveTo', + args: [19, -5] + }, { + name: 'moveTo', + args: [19, -5] + }, { + 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', function() { var mockContext = window.createMockContext(); @@ -346,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 + }, } }); @@ -357,6 +513,36 @@ describe('Line element tests', function() { 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: 'bezierCurveTo', + args: [15, -10, 19, -5, 19, -5] + }, { + 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'] @@ -403,4 +589,460 @@ describe('Line element tests', function() { args: [] }]); }); + + 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 + 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, + skip: true + } + })); + 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: [0, 10] + }, { + name: 'lineTo', + args: [3, 2] + }, { + name: 'lineTo', + args: [15, -10] + }, { + name: 'bezierCurveTo', + args: [15, -10, 19, -5, 19, -5] + }, { + 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'] + }, { + 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: [15, -10] + }, { + name: 'moveTo', + args: [15, -10] + }, { + name: 'bezierCurveTo', + args: [15, -10, 19, -5, 19, -5] + }, { + name: 'bezierCurveTo', + args: [19, -5, 0, 10, 0, 10] + }, { + name: 'stroke', + args: [], + }, { + name: 'restore', + args: [] + }]); + }); + + 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: [] + }]); + }); });