diff --git a/src/elements/element.arc.js b/src/elements/element.arc.js index e09f0cf57..209c505d9 100644 --- a/src/elements/element.arc.js +++ b/src/elements/element.arc.js @@ -37,21 +37,24 @@ var vm = this._view; - var pointRelativePosition = helpers.getAngleFromPoint(vm, { - x: chartX, - y: chartY - }); + if (vm) { + var pointRelativePosition = helpers.getAngleFromPoint(vm, { + x: chartX, + y: chartY + }); - // Put into the range of (-PI/2, 3PI/2] - var startAngle = vm.startAngle < (-0.5 * Math.PI) ? vm.startAngle + (2.0 * Math.PI) : vm.startAngle > (1.5 * Math.PI) ? vm.startAngle - (2.0 * Math.PI) : vm.startAngle; - var endAngle = vm.endAngle < (-0.5 * Math.PI) ? vm.endAngle + (2.0 * Math.PI) : vm.endAngle > (1.5 * Math.PI) ? vm.endAngle - (2.0 * Math.PI) : vm.endAngle + // Put into the range of (-PI/2, 3PI/2] + var startAngle = vm.startAngle < (-0.5 * Math.PI) ? vm.startAngle + (2.0 * Math.PI) : vm.startAngle > (1.5 * Math.PI) ? vm.startAngle - (2.0 * Math.PI) : vm.startAngle; + var endAngle = vm.endAngle < (-0.5 * Math.PI) ? vm.endAngle + (2.0 * Math.PI) : vm.endAngle > (1.5 * Math.PI) ? vm.endAngle - (2.0 * Math.PI) : vm.endAngle - //Check if within the range of the open/close angle - var betweenAngles = (pointRelativePosition.angle >= startAngle && pointRelativePosition.angle <= endAngle), - withinRadius = (pointRelativePosition.distance >= vm.innerRadius && pointRelativePosition.distance <= vm.outerRadius); + //Check if within the range of the open/close angle + var betweenAngles = (pointRelativePosition.angle >= startAngle && pointRelativePosition.angle <= endAngle), + withinRadius = (pointRelativePosition.distance >= vm.innerRadius && pointRelativePosition.distance <= vm.outerRadius); - return (betweenAngles && withinRadius); - //Ensure within the outside of the arc centre, but inside arc outer + return (betweenAngles && withinRadius); + } else { + return false; + } }, tooltipPosition: function() { var vm = this._view; diff --git a/test/element.arc.tests.js b/test/element.arc.tests.js new file mode 100644 index 000000000..4ba854575 --- /dev/null +++ b/test/element.arc.tests.js @@ -0,0 +1,176 @@ +// Test the rectangle element + +describe('Arc element tests', function() { + it ('Should be constructed', function() { + var arc = new Chart.elements.Arc({ + _datasetIndex: 2, + _index: 1 + }); + + expect(arc).not.toBe(undefined); + expect(arc._datasetIndex).toBe(2); + expect(arc._index).toBe(1); + }); + + it ('should determine if in range', function() { + var arc = new Chart.elements.Arc({ + _datasetIndex: 2, + _index: 1 + }); + + // Make sure we can run these before the view is added + expect(arc.inRange(2, 2)).toBe(false); + expect(arc.inLabelRange(2)).toBe(false); + + // Mock out the view as if the controller put it there + arc._view = { + startAngle: 0, + endAngle: Math.PI / 2, + x: 0, + y: 0, + innerRadius: 5, + outerRadius: 10, + }; + + expect(arc.inRange(2, 2)).toBe(false); + expect(arc.inRange(7, 0)).toBe(true); + expect(arc.inRange(0, 11)).toBe(false); + expect(arc.inRange(Math.sqrt(32), Math.sqrt(32))).toBe(true); + expect(arc.inRange(-1.0 * Math.sqrt(7), Math.sqrt(7))).toBe(false); + }); + + it ('should get the tooltip position', function() { + var arc = new Chart.elements.Arc({ + _datasetIndex: 2, + _index: 1 + }); + + // Mock out the view as if the controller put it there + arc._view = { + startAngle: 0, + endAngle: Math.PI / 2, + x: 0, + y: 0, + innerRadius: 0, + outerRadius: Math.sqrt(2), + }; + + var pos = arc.tooltipPosition(); + expect(pos.x).toBeCloseTo(0.5); + expect(pos.y).toBeCloseTo(0.5); + }); + + it ('should draw correctly with no border', function() { + var mockContext = window.createMockContext(); + var arc = new Chart.elements.Arc({ + _datasetIndex: 2, + _index: 1, + _chart: { + ctx: mockContext, + } + }); + + // Mock out the view as if the controller put it there + arc._view = { + startAngle: 0, + endAngle: Math.PI / 2, + x: 10, + y: 5, + innerRadius: 1, + outerRadius: 3, + + backgroundColor: 'rgb(0, 0, 255)', + borderColor: 'rgb(255, 0, 0)', + }; + + arc.draw(); + + expect(mockContext.getCalls()).toEqual([{ + name: 'beginPath', + args: [] + }, { + name: 'arc', + args: [10, 5, 3, 0, Math.PI / 2] + }, { + name: 'arc', + args: [10, 5, 1, Math.PI / 2, 0, true] + }, { + name: 'closePath', + args: [] + }, { + name: 'setStrokeStyle', + args: ['rgb(255, 0, 0)'] + }, { + name: 'setLineWidth', + args: [undefined] + }, { + name: 'setFillStyle', + args: ['rgb(0, 0, 255)'] + }, { + name: 'fill', + args: [] + }, { + name: 'setLineJoin', + args: ['bevel'] + }]); + }); + + it ('should draw correctly with a border', function() { + var mockContext = window.createMockContext(); + var arc = new Chart.elements.Arc({ + _datasetIndex: 2, + _index: 1, + _chart: { + ctx: mockContext, + } + }); + + // Mock out the view as if the controller put it there + arc._view = { + startAngle: 0, + endAngle: Math.PI / 2, + x: 10, + y: 5, + innerRadius: 1, + outerRadius: 3, + + backgroundColor: 'rgb(0, 0, 255)', + borderColor: 'rgb(255, 0, 0)', + borderWidth: 5 + }; + + arc.draw(); + + expect(mockContext.getCalls()).toEqual([{ + name: 'beginPath', + args: [] + }, { + name: 'arc', + args: [10, 5, 3, 0, Math.PI / 2] + }, { + name: 'arc', + args: [10, 5, 1, Math.PI / 2, 0, true] + }, { + name: 'closePath', + args: [] + }, { + name: 'setStrokeStyle', + args: ['rgb(255, 0, 0)'] + }, { + name: 'setLineWidth', + args: [5] + }, { + name: 'setFillStyle', + args: ['rgb(0, 0, 255)'] + }, { + name: 'fill', + args: [] + }, { + name: 'setLineJoin', + args: ['bevel'] + }, { + name: 'stroke', + args: [] + }]); + }); +}); \ No newline at end of file diff --git a/test/mockContext.js b/test/mockContext.js index 111aabbdf..f357715f1 100644 --- a/test/mockContext.js +++ b/test/mockContext.js @@ -5,6 +5,7 @@ this._initMethods(); this._fillStyle = null; + this._lineJoin = null; this._lineWidth = null; this._strokeStyle = null; @@ -17,6 +18,13 @@ this.record('setFillStyle', [style]); } }, + 'lineJoin': { + 'get': function() { return this._lineJoin; }, + 'set': function(join) { + this._lineJoin = join; + this.record('setLineJoin', [join]); + } + }, 'lineWidth': { 'get': function() { return this._lineWidth; }, 'set': function (width) {