From 73f62a9a090d29c01fa49376d44a5d44afc5c371 Mon Sep 17 00:00:00 2001 From: Akihiko Kusanagi Date: Mon, 20 May 2019 08:28:09 +0100 Subject: [PATCH] Apply lineJoin style at the first point in radar charts (#6269) --- src/elements/element.line.js | 21 +- test/specs/element.line.tests.js | 590 ------------------------------- 2 files changed, 19 insertions(+), 592 deletions(-) diff --git a/src/elements/element.line.js b/src/elements/element.line.js index 8a801f6516f..b0e799d2770 100644 --- a/src/elements/element.line.js +++ b/src/elements/element.line.js @@ -37,11 +37,24 @@ module.exports = Element.extend({ var globalDefaults = defaults.global; var globalOptionLineElements = globalDefaults.elements.line; var lastDrawnIndex = -1; + var closePath = me._loop; var index, current, previous, currentVM; - // If we are looping, adding the first point again if (me._loop && points.length) { - points.push(points[0]); + if (!spanGaps) { + for (index = points.length - 1; index >= 0; --index) { + // If the line has an open path, shift the point array + if (points[index]._view.skip) { + points = points.slice(index).concat(points.slice(0, index)); + closePath = false; + break; + } + } + } + // If the line has a close path, add the first point again + if (closePath) { + points.push(points[0]); + } } ctx.save(); @@ -90,6 +103,10 @@ module.exports = Element.extend({ } } + if (closePath) { + ctx.closePath(); + } + ctx.stroke(); ctx.restore(); } diff --git a/test/specs/element.line.tests.js b/test/specs/element.line.tests.js index a0278da4c2d..5b423ce0dad 100644 --- a/test/specs/element.line.tests.js +++ b/test/specs/element.line.tests.js @@ -1552,594 +1552,4 @@ describe('Chart.elements.Line', function() { }]; expect(mockContext.getCalls()).toEqual(expected); }); - - it('should be able to draw with a loop back to the beginning point', 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 - } - })); - - 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, // no bezier curve for now - } - }); - - line.draw(); - - expect(mockContext.getCalls()).toEqual([{ - name: 'save', - 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: [5, 0] - }, { - name: 'lineTo', - args: [15, -10] - }, { - name: 'lineTo', - args: [19, -5] - }, { - name: 'lineTo', - args: [0, 10] - }, { - name: 'stroke', - args: [], - }, { - name: 'restore', - 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, // no bezier curve for now - } - }); - - line.draw(); - - expect(mockContext.getCalls()).toEqual([{ - name: 'save', - 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: 'lineTo', - args: [19, -5] - }, { - name: 'lineTo', - args: [0, 10] - }, { - name: 'stroke', - args: [], - }, { - name: 'restore', - args: [] - }]); - }); - - it('should be able to draw with a loop back to the beginning point when span gaps is true and 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, // no bezier curve for now - spanGaps: true - } - }); - - line.draw(); - - expect(mockContext.getCalls()).toEqual([{ - name: 'save', - 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: [15, -10] - }, { - name: 'lineTo', - args: [19, -5] - }, { - name: 'lineTo', - args: [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, // no bezier curve for now - } - }); - - line.draw(); - - expect(mockContext.getCalls()).toEqual([{ - name: 'save', - 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: [5, 0] - }, { - name: 'lineTo', - args: [15, -10] - }, { - name: 'lineTo', - args: [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, // no bezier curve for now - } - }); - - line.draw(); - - expect(mockContext.getCalls()).toEqual([{ - name: 'save', - 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: [5, 0] - }, { - name: 'lineTo', - args: [15, -10] - }, { - name: 'moveTo', - args: [0, 10] - }, { - name: 'stroke', - args: [], - }, { - name: 'restore', - args: [] - }]); - }); });