//Boolean - Whether to animate scaling the chart from the centre
animate: true,
-
lineArc: false,
-
- // grid line settings
- gridLines: {
- show: true,
- color: "rgba(0, 0, 0, 0.1)",
- lineWidth: 1,
- },
+ position: "chartArea",
angleLines: {
show: true,
- color: "rgba(0,0,0, 0.1)",
+ color: "rgba(0, 0, 0, 0.1)",
lineWidth: 1
},
- // scale numbers
- reverse: false,
- beginAtZero: true,
-
// label settings
- labels: {
- show: true,
- template: "<%=value.toLocaleString()%>",
- fontSize: 12,
- fontStyle: "normal",
- fontColor: "#666",
- fontFamily: "Helvetica Neue",
-
+ ticks: {
//Boolean - Show a backdrop to the scale label
showLabelBackdrop: true,
},
};
- var LinearRadialScale = Chart.Element.extend({
- initialize: function() {
- this.height = this.chart.height;
- this.width = this.chart.width;
- this.xCenter = this.chart.width / 2;
- this.yCenter = this.chart.height / 2;
- this.size = helpers.min([this.height, this.width]);
- this.labels = this.data.labels;
- this.drawingArea = (this.options.display) ? (this.size / 2) - (this.options.labels.fontSize / 2 + this.options.labels.backdropPaddingY) : (this.size / 2);
- },
+ var LinearRadialScale = Chart.Scale.extend({
getValueCount: function() {
return this.data.labels.length;
},
- update: function() {
- if (!this.options.lineArc) {
- this.setScaleSize();
- } else {
- this.drawingArea = (this.options.display) ? (this.size / 2) - (this.fontSize / 2 + this.backdropPaddingY) : (this.size / 2);
- }
-
- this.buildYLabels();
+ setDimensions: function() {
+ // Set the unconstrained dimension before label rotation
+ this.width = this.maxWidth;
+ this.height = this.maxHeight;
+ this.xCenter = Math.round(this.width / 2);
+ this.yCenter = Math.round(this.height / 2);
+
+ var minSize = helpers.min([this.height, this.width]);
+ this.drawingArea = (this.options.display) ? (minSize / 2) - (this.options.ticks.fontSize / 2 + this.options.ticks.backdropPaddingY) : (minSize / 2);
},
- calculateRange: function() {
+ buildTicks: function() {
this.min = null;
this.max = null;
}
}, this);
}, this);
- },
- generateTicks: function() {
- // We need to decide how many ticks we are going to have. Each tick draws a grid line.
- // There are two possibilities. The first is that the user has manually overridden the scale
- // calculations in which case the job is easy. The other case is that we have to do it ourselves
- //
- // We assume at this point that the scale object has been updated with the following values
- // by the chart.
- // min: this is the minimum value of the scale
- // max: this is the maximum value of the scale
- // options: contains the options for the scale. This is referenced from the user settings
- // rather than being cloned. This ensures that updates always propogate to a redraw
-
- // Reset the ticks array. Later on, we will draw a grid line at these positions
- // The array simply contains the numerical value of the spots where ticks will be
- this.ticks = [];
- if (this.options.override) {
- // The user has specified the manual override. We use <= instead of < so that
- // we get the final line
- for (var i = 0; i <= this.options.override.steps; ++i) {
- var value = this.options.override.start + (i * this.options.override.stepWidth);
- this.ticks.push(value);
- }
- } else {
- // Figure out what the max number of ticks we can support it is based on the size of
- // the axis area. For now, we say that the minimum tick spacing in pixels must be 50
- // We also limit the maximum number of ticks to 11 which gives a nice 10 squares on
- // the graph
-
- var maxTicks = Math.min(11, Math.ceil(this.drawingArea / (2 * this.options.labels.fontSize)));
-
- // Make sure we always have at least 2 ticks
- maxTicks = Math.max(2, maxTicks);
-
- // To get a "nice" value for the tick spacing, we will use the appropriately named
- // "nice number" algorithm. See http://stackoverflow.com/questions/8506881/nice-label-algorithm-for-charts-with-minimum-ticks
- // for details.
-
- // If we are forcing it to begin at 0, but 0 will already be rendered on the chart,
- // do nothing since that would make the chart weird. If the user really wants a weird chart
- // axis, they can manually override it
- if (this.options.beginAtZero) {
- var minSign = helpers.sign(this.min);
- var maxSign = helpers.sign(this.max);
-
- if (minSign < 0 && maxSign < 0) {
- // move the top up to 0
- this.max = 0;
- } else if (minSign > 0 && maxSign > 0) {
- // move the botttom down to 0
- this.min = 0;
- }
- }
+ if (this.min === this.max) {
+ this.min--;
+ this.max++;
+ }
- var niceRange = helpers.niceNum(this.max - this.min, false);
- var spacing = helpers.niceNum(niceRange / (maxTicks - 1), true);
- var niceMin = Math.floor(this.min / spacing) * spacing;
- var niceMax = Math.ceil(this.max / spacing) * spacing;
+ this.ticks = [];
- // Put the values into the ticks array
- for (var j = niceMin; j <= niceMax; j += spacing) {
- this.ticks.push(j);
+ // Figure out what the max number of ticks we can support it is based on the size of
+ // the axis area. For now, we say that the minimum tick spacing in pixels must be 50
+ // We also limit the maximum number of ticks to 11 which gives a nice 10 squares on
+ // the graph
+ var maxTicks = Math.min(11, Math.ceil(this.drawingArea / (1.5 * this.options.ticks.fontSize)));
+ maxTicks = Math.max(2, maxTicks); // Make sure we always have at least 2 ticks
+
+ // To get a "nice" value for the tick spacing, we will use the appropriately named
+ // "nice number" algorithm. See http://stackoverflow.com/questions/8506881/nice-label-algorithm-for-charts-with-minimum-ticks
+ // for details.
+
+ // If we are forcing it to begin at 0, but 0 will already be rendered on the chart,
+ // do nothing since that would make the chart weird. If the user really wants a weird chart
+ // axis, they can manually override it
+ if (this.options.ticks.beginAtZero) {
+ var minSign = helpers.sign(this.min);
+ var maxSign = helpers.sign(this.max);
+
+ if (minSign < 0 && maxSign < 0) {
+ // move the top up to 0
+ this.max = 0;
+ } else if (minSign > 0 && maxSign > 0) {
+ // move the botttom down to 0
+ this.min = 0;
}
}
- if (this.options.position == "left" || this.options.position == "right") {
- // We are in a vertical orientation. The top value is the highest. So reverse the array
- this.ticks.reverse();
+ var niceRange = helpers.niceNum(this.max - this.min, false);
+ var spacing = helpers.niceNum(niceRange / (maxTicks - 1), true);
+ var niceMin = Math.floor(this.min / spacing) * spacing;
+ var niceMax = Math.ceil(this.max / spacing) * spacing;
+
+ // Put the values into the ticks array
+ for (var j = niceMin; j <= niceMax; j += spacing) {
+ this.ticks.push(j);
}
// At this point, we need to update our max and min given the tick values since we have expanded the
// range of the scale
this.max = helpers.max(this.ticks);
this.min = helpers.min(this.ticks);
- },
- buildYLabels: function() {
- this.yLabels = [];
-
- helpers.each(this.ticks, function(tick, index, ticks) {
- var label;
-
- if (this.options.labels.userCallback) {
- // If the user provided a callback for label generation, use that as first priority
- label = this.options.labels.userCallback(tick, index, ticks);
- } else if (this.options.labels.template) {
- // else fall back to the template string
- label = helpers.template(this.options.labels.template, {
- value: tick
- });
- }
- this.yLabels.push(label ? label : "");
- }, this);
+ if (this.options.ticks.reverse) {
+ this.ticks.reverse();
+
+ this.start = this.max;
+ this.end = this.min;
+ } else {
+ this.start = this.min;
+ this.end = this.max;
+ }
+
+ this.zeroLineIndex = this.ticks.indexOf(0);
},
getCircumference: function() {
return ((Math.PI * 2) / this.getValueCount());
},
- setScaleSize: function() {
+ fit: function() {
/*
* Right, this is really confusing and there is a lot of maths going on here
* The gist of the problem is here: https://gist.github.com/nnnick/696cc9c55f4b0beb8fe9
for (i = 0; i < this.getValueCount(); i++) {
// 5px to space the text slightly out - similar to what we do in the draw function.
pointPosition = this.getPointPosition(i, largestPossibleRadius);
- textWidth = this.ctx.measureText(helpers.template(this.options.labels.template, {
- value: this.labels[i]
+ textWidth = this.ctx.measureText(helpers.template(this.options.ticks.template, {
+ value: this.data.labels[i]
})).width + 5;
if (i === 0 || i === this.getValueCount() / 2) {
// If we're at index zero, or exactly the middle, we're at exactly the top/bottom
}
xProtrusionLeft = furthestLeft;
-
xProtrusionRight = Math.ceil(furthestRight - this.width);
furthestRightAngle = this.getIndexAngle(furthestRightIndex);
-
furthestLeftAngle = this.getIndexAngle(furthestLeftIndex);
radiusReductionRight = xProtrusionRight / Math.sin(furthestRightAngle + Math.PI / 2);
-
radiusReductionLeft = xProtrusionLeft / Math.sin(furthestLeftAngle + Math.PI / 2);
// Ensure we actually need to reduce the size of the chart
radiusReductionRight = (helpers.isNumber(radiusReductionRight)) ? radiusReductionRight : 0;
radiusReductionLeft = (helpers.isNumber(radiusReductionLeft)) ? radiusReductionLeft : 0;
- this.drawingArea = largestPossibleRadius - (radiusReductionLeft + radiusReductionRight) / 2;
-
- //this.drawingArea = min([maxWidthRadius, (this.height - (2 * (this.pointLabelFontSize + 5)))/2])
+ this.drawingArea = Math.round(largestPossibleRadius - (radiusReductionLeft + radiusReductionRight) / 2);
this.setCenterPoint(radiusReductionLeft, radiusReductionRight);
-
},
setCenterPoint: function(leftMovement, rightMovement) {
var maxRight = this.width - rightMovement - this.drawingArea,
maxLeft = leftMovement + this.drawingArea;
- this.xCenter = (maxLeft + maxRight) / 2;
+ this.xCenter = Math.round(((maxLeft + maxRight) / 2) + this.left);
// Always vertically in the centre as the text height doesn't change
- this.yCenter = (this.height / 2);
+ this.yCenter = Math.round((this.height / 2) + this.top);
},
getIndexAngle: function(index) {
draw: function() {
if (this.options.display) {
var ctx = this.ctx;
- helpers.each(this.yLabels, function(label, index) {
+ helpers.each(this.ticks, function(label, index) {
// Don't draw a centre value (if it is minimum)
if (index > 0 || this.options.reverse) {
var yCenterOffset = this.getDistanceFromCenterForValue(this.ticks[index]);
}
}
- if (this.options.labels.show) {
- ctx.font = helpers.fontString(this.options.labels.fontSize, this.options.labels.fontStyle, this.options.labels.fontFamily);
+ if (this.options.ticks.show) {
+ ctx.font = helpers.fontString(this.options.ticks.fontSize, this.options.ticks.fontStyle, this.options.ticks.fontFamily);
- if (this.options.labels.showLabelBackdrop) {
+ if (this.options.ticks.showLabelBackdrop) {
var labelWidth = ctx.measureText(label).width;
- ctx.fillStyle = this.options.labels.backdropColor;
+ ctx.fillStyle = this.options.ticks.backdropColor;
ctx.fillRect(
- this.xCenter - labelWidth / 2 - this.options.labels.backdropPaddingX,
- yHeight - this.fontSize / 2 - this.options.labels.backdropPaddingY,
- labelWidth + this.options.labels.backdropPaddingX * 2,
- this.options.labels.fontSize + this.options.labels.backdropPaddingY * 2
+ this.xCenter - labelWidth / 2 - this.options.ticks.backdropPaddingX,
+ yHeight - this.options.ticks.fontSize / 2 - this.options.ticks.backdropPaddingY,
+ labelWidth + this.options.ticks.backdropPaddingX * 2,
+ this.options.ticks.fontSize + this.options.ticks.backdropPaddingY * 2
);
}
ctx.textAlign = 'center';
ctx.textBaseline = "middle";
- ctx.fillStyle = this.options.labels.fontColor;
+ ctx.fillStyle = this.options.ticks.fontColor;
ctx.fillText(label, this.xCenter, yHeight);
}
}
ctx.font = helpers.fontString(this.options.pointLabels.fontSize, this.options.pointLabels.fontStyle, this.options.pointLabels.fontFamily);
ctx.fillStyle = this.options.pointLabels.fontColor;
- var labelsCount = this.labels.length,
- halfLabelsCount = this.labels.length / 2,
+ var labelsCount = this.data.labels.length,
+ halfLabelsCount = this.data.labels.length / 2,
quarterLabelsCount = halfLabelsCount / 2,
upperHalf = (i < quarterLabelsCount || i > labelsCount - quarterLabelsCount),
exactQuarter = (i === quarterLabelsCount || i === labelsCount - quarterLabelsCount);
ctx.textBaseline = 'top';
}
- ctx.fillText(this.labels[i], pointLabelPosition.x, pointLabelPosition.y);
+ ctx.fillText(this.data.labels[i], pointLabelPosition.x, pointLabelPosition.y);
}
}
}
--- /dev/null
+// Tests for the radial linear scale used by the polar area and radar charts
+describe('Test the radial linear scale', function() {
+ it('Should register the constructor with the scale service', function() {
+ var Constructor = Chart.scaleService.getScaleConstructor('radialLinear');
+ expect(Constructor).not.toBe(undefined);
+ expect(typeof Constructor).toBe('function');
+ });
+
+ it('Should have the correct default config', function() {
+ var defaultConfig = Chart.scaleService.getScaleDefaults('radialLinear');
+ expect(defaultConfig).toEqual({
+ angleLines: {
+ show: true,
+ color: "rgba(0, 0, 0, 0.1)",
+ lineWidth: 1
+ },
+ animate: true,
+ display: true,
+ gridLines: {
+ color: "rgba(0, 0, 0, 0.1)",
+ drawOnChartArea: true,
+ drawTicks: true,
+ lineWidth: 1,
+ offsetGridLines: false,
+ show: true,
+ zeroLineColor: "rgba(0,0,0,0.25)",
+ zeroLineWidth: 1,
+ },
+ lineArc: false,
+ pointLabels: {
+ fontColor: "#666",
+ fontFamily: "'Arial'",
+ fontSize: 10,
+ fontStyle: "normal",
+ },
+ position: "chartArea",
+ scaleLabel: {
+ fontColor: '#666',
+ fontFamily: 'Helvetica Neue',
+ fontSize: 12,
+ fontStyle: 'normal',
+ labelString: '',
+ show: false,
+ },
+ ticks: {
+ backdropColor: "rgba(255,255,255,0.75)",
+ backdropPaddingY: 2,
+ backdropPaddingX: 2,
+ beginAtZero: false,
+ fontColor: "#666",
+ fontFamily: "Helvetica Neue",
+ fontSize: 12,
+ fontStyle: "normal",
+ maxRotation: 90,
+ minRotation: 20,
+ mirror: false,
+ padding: 10,
+ reverse: false,
+ showLabelBackdrop: true,
+ show: true,
+ template: "<%=value%>",
+
+ },
+ });
+ });
+
+ it('Should correctly determine the max & min data values', function() {
+ var scaleID = 'myScale';
+
+ var mockData = {
+ datasets: [{
+ yAxisID: scaleID,
+ data: [10, 5, 0, -5, 78, -100]
+ }, {
+ yAxisID: scaleID,
+ data: [150]
+ }],
+ labels: ['lablel1', 'label2', 'label3', 'label4', 'label5', 'label6']
+ };
+
+ var mockContext = window.createMockContext();
+ var Constructor = Chart.scaleService.getScaleConstructor('radialLinear');
+ var scale = new Constructor({
+ ctx: mockContext,
+ options: Chart.scaleService.getScaleDefaults('radialLinear'), // use default config for scale
+ data: mockData,
+ id: scaleID,
+ });
+
+ scale.update(200, 300);
+ expect(scale.min).toBe(-100);
+ expect(scale.max).toBe(200);
+ });
+
+ it('Should ensure that the scale has a max and min that are not equal', function() {
+ var scaleID = 'myScale';
+
+ var mockData = {
+ datasets: [],
+ labels: []
+ };
+
+ var mockContext = window.createMockContext();
+ var Constructor = Chart.scaleService.getScaleConstructor('radialLinear');
+ var scale = new Constructor({
+ ctx: mockContext,
+ options: Chart.scaleService.getScaleDefaults('radialLinear'), // use default config for scale
+ data: mockData,
+ id: scaleID,
+ });
+
+ scale.update(200, 300);
+ expect(scale.min).toBe(-1);
+ expect(scale.max).toBe(1);
+ });
+
+ it('should forcibly include 0 in the range if the beginAtZero option is used', function() {
+ var scaleID = 'myScale';
+
+ var mockData = {
+ datasets: [{
+ yAxisID: scaleID,
+ data: [20, 30, 40, 50]
+ }],
+ labels: [],
+ };
+
+ var mockContext = window.createMockContext();
+ var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('radialLinear'));
+ var Constructor = Chart.scaleService.getScaleConstructor('radialLinear');
+ var scale = new Constructor({
+ ctx: mockContext,
+ options: config,
+ data: mockData,
+ id: scaleID,
+ });
+
+ config.ticks.beginAtZero = false;
+ scale.update(400, 400);
+ expect(scale.ticks).toEqual(['20', '25', '30', '35', '40', '45', '50']);
+
+ config.ticks.beginAtZero = true;
+ scale.update(400, 400);
+ expect(scale.ticks).toEqual(['0', '5', '10', '15', '20', '25', '30', '35', '40', '45', '50']);
+
+ mockData.datasets[0].data = [-20, -30, -40, -50];
+ scale.update(400, 400);
+ expect(scale.ticks).toEqual(['-50', '-45', '-40', '-35', '-30', '-25', '-20', '-15', '-10', '-5', '0']);
+
+ config.ticks.beginAtZero = false;
+ scale.update(400, 400);
+ expect(scale.ticks).toEqual(['-50', '-45', '-40', '-35', '-30', '-25', '-20']);
+ });
+
+ it('Should generate tick marks in the correct order in reversed mode', function() {
+ var scaleID = 'myScale';
+
+ var mockData = {
+ datasets: [{
+ yAxisID: scaleID,
+ data: [10, 5, 0, 25, 78]
+ }],
+ labels: []
+ };
+
+ var mockContext = window.createMockContext();
+ var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('radialLinear'));
+ config.ticks.reverse = true;
+ var Constructor = Chart.scaleService.getScaleConstructor('radialLinear');
+ var scale = new Constructor({
+ ctx: mockContext,
+ options: config,
+ data: mockData,
+ id: scaleID,
+ });
+
+ scale.update(200, 300);
+
+ // Reverse mode makes this count up
+ expect(scale.ticks).toEqual(['80', '60', '40', '20', '0']);
+ expect(scale.start).toBe(80);
+ expect(scale.end).toBe(0);
+ });
+
+ it('Should build labels using the user supplied callback', function() {
+ var scaleID = 'myScale';
+
+ var mockData = {
+ datasets: [{
+ yAxisID: scaleID,
+ data: [10, 5, 0, 25, 78]
+ }],
+ labels: []
+ };
+
+ var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('radialLinear'));
+ config.ticks.userCallback = function(value, index) {
+ return index.toString();
+ };
+
+ var mockContext = window.createMockContext();
+ var Constructor = Chart.scaleService.getScaleConstructor('radialLinear');
+ var scale = new Constructor({
+ ctx: mockContext,
+ options: config,
+ data: mockData,
+ id: scaleID,
+ });
+
+ scale.update(200, 300);
+
+ // Just the index
+ expect(scale.ticks).toEqual(['0', '1', '2', '3', '4']);
+ });
+
+ it('should correctly set the center point', function() {
+ var scaleID = 'myScale';
+
+ var mockData = {
+ datasets: [{
+ yAxisID: scaleID,
+ data: [10, 5, 0, 25, 78]
+ }],
+ labels: ['point1', 'point2', 'point3', 'point4', 'point5'] // used in radar charts which use the same scales
+ };
+
+ var mockContext = window.createMockContext();
+ var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('radialLinear'));
+ var Constructor = Chart.scaleService.getScaleConstructor('radialLinear');
+ var scale = new Constructor({
+ ctx: mockContext,
+ options: config,
+ data: mockData,
+ id: scaleID,
+ });
+
+ scale.left = 10;
+ scale.right = 210;
+ scale.top = 5;
+ scale.bottom = 305;
+ scale.update(200, 300);
+
+ expect(scale.drawingArea).toBe(36);
+ expect(scale.xCenter).toBe(110);
+ expect(scale.yCenter).toBe(155);
+ });
+
+ it('should get the correct distance from the center point', function() {
+ var scaleID = 'myScale';
+
+ var mockData = {
+ datasets: [{
+ yAxisID: scaleID,
+ data: [10, 5, 0, 25, 78]
+ }],
+ labels: ['point1', 'point2', 'point3', 'point4', 'point5'] // used in radar charts which use the same scales
+ };
+
+ var mockContext = window.createMockContext();
+ var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('radialLinear'));
+ var Constructor = Chart.scaleService.getScaleConstructor('radialLinear');
+ var scale = new Constructor({
+ ctx: mockContext,
+ options: config,
+ data: mockData,
+ id: scaleID,
+ });
+
+ scale.left = 0;
+ scale.right = 200;
+ scale.top = 0;
+ scale.bottom = 300;
+ scale.update(200, 300);
+
+ expect(scale.getDistanceFromCenterForValue(scale.min)).toBe(0);
+ expect(scale.getDistanceFromCenterForValue(scale.max)).toBe(36);
+ expect(scale.getPointPositionForValue(1, 5)).toEqual({
+ x: 102.13987716166409,
+ y: 149.30471176265638,
+ });
+
+ config.reverse = true;
+
+ scale.update(200, 300);
+
+ expect(scale.getDistanceFromCenterForValue(scale.min)).toBe(36);
+ expect(scale.getDistanceFromCenterForValue(scale.max)).toBe(0);
+ });
+
+ it('should draw correctly when there are no point labels', function() {
+ var scaleID = 'myScale';
+
+ var mockData = {
+ datasets: [{
+ yAxisID: scaleID,
+ data: [10, 5, 0, 25, 78]
+ }, ],
+ labels: ['point1', 'point2', 'point3', 'point4', 'point5'] // used in radar charts which use the same scales
+ };
+
+ var mockContext = window.createMockContext();
+ var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('radialLinear'));
+ config.lineArc = true;
+ var Constructor = Chart.scaleService.getScaleConstructor('radialLinear');
+ var scale = new Constructor({
+ ctx: mockContext,
+ options: config,
+ data: mockData,
+ id: scaleID,
+ });
+
+ scale.left = 0;
+ scale.right = 200;
+ scale.top = 0;
+ scale.bottom = 300;
+ scale.update(200, 300);
+
+ scale.draw();
+
+ var expected = [{
+ "name": "measureText",
+ "args": ["0"]
+ }, {
+ "name": "measureText",
+ "args": ["80"]
+ }, {
+ "name": "measureText",
+ "args": ["point1"]
+ }, {
+ "name": "measureText",
+ "args": ["point2"]
+ }, {
+ "name": "measureText",
+ "args": ["point3"]
+ }, {
+ "name": "measureText",
+ "args": ["point4"]
+ }, {
+ "name": "measureText",
+ "args": ["point5"]
+ }, {
+ "name": "setStrokeStyle",
+ "args": ["rgba(0, 0, 0, 0.1)"]
+ }, {
+ "name": "setLineWidth",
+ "args": [1]
+ }, {
+ "name": "beginPath",
+ "args": []
+ }, {
+ "name": "arc",
+ "args": [100, 150, 9, 0, 6.283185307179586]
+ }, {
+ "name": "closePath",
+ "args": []
+ }, {
+ "name": "stroke",
+ "args": []
+ }, {
+ "name": "measureText",
+ "args": ["20"]
+ }, {
+ "name": "setFillStyle",
+ "args": ["rgba(255,255,255,0.75)"]
+ }, {
+ "name": "fillRect",
+ "args": [88, 133, 24, 16]
+ }, {
+ "name": "setFillStyle",
+ "args": ["#666"]
+ }, {
+ "name": "fillText",
+ "args": ["20", 100, 141]
+ }, {
+ "name": "setStrokeStyle",
+ "args": ["rgba(0, 0, 0, 0.1)"]
+ }, {
+ "name": "setLineWidth",
+ "args": [1]
+ }, {
+ "name": "beginPath",
+ "args": []
+ }, {
+ "name": "arc",
+ "args": [100, 150, 18, 0, 6.283185307179586]
+ }, {
+ "name": "closePath",
+ "args": []
+ }, {
+ "name": "stroke",
+ "args": []
+ }, {
+ "name": "measureText",
+ "args": ["40"]
+ }, {
+ "name": "setFillStyle",
+ "args": ["rgba(255,255,255,0.75)"]
+ }, {
+ "name": "fillRect",
+ "args": [88, 124, 24, 16]
+ }, {
+ "name": "setFillStyle",
+ "args": ["#666"]
+ }, {
+ "name": "fillText",
+ "args": ["40", 100, 132]
+ }, {
+ "name": "setStrokeStyle",
+ "args": ["rgba(0, 0, 0, 0.1)"]
+ }, {
+ "name": "setLineWidth",
+ "args": [1]
+ }, {
+ "name": "beginPath",
+ "args": []
+ }, {
+ "name": "arc",
+ "args": [100, 150, 27, 0, 6.283185307179586]
+ }, {
+ "name": "closePath",
+ "args": []
+ }, {
+ "name": "stroke",
+ "args": []
+ }, {
+ "name": "measureText",
+ "args": ["60"]
+ }, {
+ "name": "setFillStyle",
+ "args": ["rgba(255,255,255,0.75)"]
+ }, {
+ "name": "fillRect",
+ "args": [88, 115, 24, 16]
+ }, {
+ "name": "setFillStyle",
+ "args": ["#666"]
+ }, {
+ "name": "fillText",
+ "args": ["60", 100, 123]
+ }, {
+ "name": "setStrokeStyle",
+ "args": ["rgba(0, 0, 0, 0.1)"]
+ }, {
+ "name": "setLineWidth",
+ "args": [1]
+ }, {
+ "name": "beginPath",
+ "args": []
+ }, {
+ "name": "arc",
+ "args": [100, 150, 36, 0, 6.283185307179586]
+ }, {
+ "name": "closePath",
+ "args": []
+ }, {
+ "name": "stroke",
+ "args": []
+ }, {
+ "name": "measureText",
+ "args": ["80"]
+ }, {
+ "name": "setFillStyle",
+ "args": ["rgba(255,255,255,0.75)"]
+ }, {
+ "name": "fillRect",
+ "args": [88, 106, 24, 16]
+ }, {
+ "name": "setFillStyle",
+ "args": ["#666"]
+ }, {
+ "name": "fillText",
+ "args": ["80", 100, 114]
+ }];
+ expect(mockContext.getCalls()).toEqual(expected);
+
+ mockContext.resetCalls();
+ config.lineArc = false;
+ scale.draw();
+
+ expect(mockContext.getCalls()).toEqual([{
+ "name": "setStrokeStyle",
+ "args": ["rgba(0, 0, 0, 0.1)"]
+ }, {
+ "name": "setLineWidth",
+ "args": [1]
+ }, {
+ "name": "beginPath",
+ "args": []
+ }, {
+ "name": "moveTo",
+ "args": [100, 141]
+ }, {
+ "name": "lineTo",
+ "args": [108.55950864665638, 147.21884705062547]
+ }, {
+ "name": "lineTo",
+ "args": [105.29006727063226, 157.28115294937453]
+ }, {
+ "name": "lineTo",
+ "args": [94.70993272936774, 157.28115294937453]
+ }, {
+ "name": "lineTo",
+ "args": [91.44049135334362, 147.21884705062547]
+ }, {
+ "name": "closePath",
+ "args": []
+ }, {
+ "name": "stroke",
+ "args": []
+ }, {
+ "name": "measureText",
+ "args": ["20"]
+ }, {
+ "name": "setFillStyle",
+ "args": ["rgba(255,255,255,0.75)"]
+ }, {
+ "name": "fillRect",
+ "args": [88, 133, 24, 16]
+ }, {
+ "name": "setFillStyle",
+ "args": ["#666"]
+ }, {
+ "name": "fillText",
+ "args": ["20", 100, 141]
+ }, {
+ "name": "setStrokeStyle",
+ "args": ["rgba(0, 0, 0, 0.1)"]
+ }, {
+ "name": "setLineWidth",
+ "args": [1]
+ }, {
+ "name": "beginPath",
+ "args": []
+ }, {
+ "name": "moveTo",
+ "args": [100, 132]
+ }, {
+ "name": "lineTo",
+ "args": [117.11901729331277, 144.43769410125094]
+ }, {
+ "name": "lineTo",
+ "args": [110.58013454126451, 164.56230589874906]
+ }, {
+ "name": "lineTo",
+ "args": [89.41986545873549, 164.56230589874906]
+ }, {
+ "name": "lineTo",
+ "args": [82.88098270668723, 144.43769410125094]
+ }, {
+ "name": "closePath",
+ "args": []
+ }, {
+ "name": "stroke",
+ "args": []
+ }, {
+ "name": "measureText",
+ "args": ["40"]
+ }, {
+ "name": "setFillStyle",
+ "args": ["rgba(255,255,255,0.75)"]
+ }, {
+ "name": "fillRect",
+ "args": [88, 124, 24, 16]
+ }, {
+ "name": "setFillStyle",
+ "args": ["#666"]
+ }, {
+ "name": "fillText",
+ "args": ["40", 100, 132]
+ }, {
+ "name": "setStrokeStyle",
+ "args": ["rgba(0, 0, 0, 0.1)"]
+ }, {
+ "name": "setLineWidth",
+ "args": [1]
+ }, {
+ "name": "beginPath",
+ "args": []
+ }, {
+ "name": "moveTo",
+ "args": [100, 123]
+ }, {
+ "name": "lineTo",
+ "args": [125.67852593996915, 141.6565411518764]
+ }, {
+ "name": "lineTo",
+ "args": [115.87020181189678, 171.8434588481236]
+ }, {
+ "name": "lineTo",
+ "args": [84.12979818810322, 171.8434588481236]
+ }, {
+ "name": "lineTo",
+ "args": [74.32147406003085, 141.6565411518764]
+ }, {
+ "name": "closePath",
+ "args": []
+ }, {
+ "name": "stroke",
+ "args": []
+ }, {
+ "name": "measureText",
+ "args": ["60"]
+ }, {
+ "name": "setFillStyle",
+ "args": ["rgba(255,255,255,0.75)"]
+ }, {
+ "name": "fillRect",
+ "args": [88, 115, 24, 16]
+ }, {
+ "name": "setFillStyle",
+ "args": ["#666"]
+ }, {
+ "name": "fillText",
+ "args": ["60", 100, 123]
+ }, {
+ "name": "setStrokeStyle",
+ "args": ["rgba(0, 0, 0, 0.1)"]
+ }, {
+ "name": "setLineWidth",
+ "args": [1]
+ }, {
+ "name": "beginPath",
+ "args": []
+ }, {
+ "name": "moveTo",
+ "args": [100, 114]
+ }, {
+ "name": "lineTo",
+ "args": [134.23803458662553, 138.87538820250188]
+ }, {
+ "name": "lineTo",
+ "args": [121.16026908252903, 179.12461179749812]
+ }, {
+ "name": "lineTo",
+ "args": [78.83973091747097, 179.12461179749812]
+ }, {
+ "name": "lineTo",
+ "args": [65.76196541337447, 138.8753882025019]
+ }, {
+ "name": "closePath",
+ "args": []
+ }, {
+ "name": "stroke",
+ "args": []
+ }, {
+ "name": "measureText",
+ "args": ["80"]
+ }, {
+ "name": "setFillStyle",
+ "args": ["rgba(255,255,255,0.75)"]
+ }, {
+ "name": "fillRect",
+ "args": [88, 106, 24, 16]
+ }, {
+ "name": "setFillStyle",
+ "args": ["#666"]
+ }, {
+ "name": "fillText",
+ "args": ["80", 100, 114]
+ }, {
+ "name": "setLineWidth",
+ "args": [1]
+ }, {
+ "name": "setStrokeStyle",
+ "args": ["rgba(0, 0, 0, 0.1)"]
+ }, {
+ "name": "beginPath",
+ "args": []
+ }, {
+ "name": "moveTo",
+ "args": [100, 150]
+ }, {
+ "name": "lineTo",
+ "args": [65.76196541337447, 138.8753882025019]
+ }, {
+ "name": "stroke",
+ "args": []
+ }, {
+ "name": "closePath",
+ "args": []
+ }, {
+ "name": "setFillStyle",
+ "args": ["#666"]
+ }, {
+ "name": "fillText",
+ "args": ["point5", 61.0066828318987, 137.33030323062715]
+ }, {
+ "name": "beginPath",
+ "args": []
+ }, {
+ "name": "moveTo",
+ "args": [100, 150]
+ }, {
+ "name": "lineTo",
+ "args": [78.83973091747097, 179.12461179749812]
+ }, {
+ "name": "stroke",
+ "args": []
+ }, {
+ "name": "closePath",
+ "args": []
+ }, {
+ "name": "setFillStyle",
+ "args": ["#666"]
+ }, {
+ "name": "fillText",
+ "args": ["point4", 75.9008046560086, 183.16969676937285]
+ }, {
+ "name": "beginPath",
+ "args": []
+ }, {
+ "name": "moveTo",
+ "args": [100, 150]
+ }, {
+ "name": "lineTo",
+ "args": [121.16026908252903, 179.12461179749812]
+ }, {
+ "name": "stroke",
+ "args": []
+ }, {
+ "name": "closePath",
+ "args": []
+ }, {
+ "name": "setFillStyle",
+ "args": ["#666"]
+ }, {
+ "name": "fillText",
+ "args": ["point3", 124.0991953439914, 183.16969676937285]
+ }, {
+ "name": "beginPath",
+ "args": []
+ }, {
+ "name": "moveTo",
+ "args": [100, 150]
+ }, {
+ "name": "lineTo",
+ "args": [134.23803458662553, 138.87538820250188]
+ }, {
+ "name": "stroke",
+ "args": []
+ }, {
+ "name": "closePath",
+ "args": []
+ }, {
+ "name": "setFillStyle",
+ "args": ["#666"]
+ }, {
+ "name": "fillText",
+ "args": ["point2", 138.9933171681013, 137.33030323062715]
+ }, {
+ "name": "beginPath",
+ "args": []
+ }, {
+ "name": "moveTo",
+ "args": [100, 150]
+ }, {
+ "name": "lineTo",
+ "args": [100, 114]
+ }, {
+ "name": "stroke",
+ "args": []
+ }, {
+ "name": "closePath",
+ "args": []
+ }, {
+ "name": "setFillStyle",
+ "args": ["#666"]
+ }, {
+ "name": "fillText",
+ "args": ["point1", 100, 109]
+ }]);
+ });
+});
\ No newline at end of file