mirror of
https://github.com/chartjs/Chart.js.git
synced 2025-12-08 20:36:08 +00:00
Refactoring of the line drawing function to make spanGaps work correctly. Added a lot more test conditions to the line element tests. Ensured that the line controller correctly calculated bezier control points when there was a point to be skipped
This commit is contained in:
parent
e94d3c0730
commit
2016630daa
@ -247,7 +247,9 @@ module.exports = function(Chart) {
|
||||
var me = this;
|
||||
var meta = me.getMeta();
|
||||
var area = me.chart.chartArea;
|
||||
var points = meta.data || [];
|
||||
|
||||
// only consider points that are drawn in case the spanGaps option is ued
|
||||
var points = (meta.data || []).filter(function(pt) { return !pt._model.skip; });
|
||||
var i, ilen, point, model, controlPoints;
|
||||
|
||||
var needToCap = me.chart.options.elements.line.capBezierPoints;
|
||||
|
||||
@ -19,107 +19,104 @@ module.exports = function(Chart) {
|
||||
};
|
||||
|
||||
Chart.elements.Line = Chart.Element.extend({
|
||||
lineToNextPoint: function(previousPoint, point, nextPoint, skipHandler, previousSkipHandler) {
|
||||
var me = this;
|
||||
var ctx = me._chart.ctx;
|
||||
var spanGaps = me._view ? me._view.spanGaps : false;
|
||||
|
||||
if (point._view.skip && !spanGaps) {
|
||||
skipHandler.call(me, previousPoint, point, nextPoint);
|
||||
} else if (previousPoint._view.skip && !spanGaps) {
|
||||
previousSkipHandler.call(me, previousPoint, point, nextPoint);
|
||||
} else if (point._view.steppedLine === true) {
|
||||
ctx.lineTo(point._view.x, previousPoint._view.y);
|
||||
ctx.lineTo(point._view.x, point._view.y);
|
||||
} else if (point._view.tension === 0) {
|
||||
ctx.lineTo(point._view.x, point._view.y);
|
||||
} 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 me = this;
|
||||
|
||||
var vm = me._view;
|
||||
var ctx = me._chart.ctx;
|
||||
var first = me._children[0];
|
||||
var last = me._children[me._children.length - 1];
|
||||
var spanGaps = vm.spanGaps;
|
||||
var scaleZero = vm.scaleZero;
|
||||
var loop = me._loop;
|
||||
|
||||
function loopBackToStart(drawLineToCenter) {
|
||||
if (!first._view.skip && !last._view.skip) {
|
||||
// Draw a bezier line from last to first
|
||||
var ctx = me._chart.ctx;
|
||||
ctx.save();
|
||||
|
||||
// Helper function to draw a line to a point
|
||||
function lineToPoint(previousPoint, point) {
|
||||
var vm = point._view;
|
||||
if (point._view.steppedLine === true) {
|
||||
ctx.lineTo(point._view.x, previousPoint._view.y);
|
||||
ctx.lineTo(point._view.x, point._view.y);
|
||||
} else if (point._view.tension === 0) {
|
||||
ctx.lineTo(vm.x, vm.y);
|
||||
} else {
|
||||
ctx.bezierCurveTo(
|
||||
last._view.controlPointNextX,
|
||||
last._view.controlPointNextY,
|
||||
first._view.controlPointPreviousX,
|
||||
first._view.controlPointPreviousY,
|
||||
first._view.x,
|
||||
first._view.y
|
||||
previousPoint._view.controlPointNextX,
|
||||
previousPoint._view.controlPointNextY,
|
||||
vm.controlPointPreviousX,
|
||||
vm.controlPointPreviousY,
|
||||
vm.x,
|
||||
vm.y
|
||||
);
|
||||
} else if (drawLineToCenter) {
|
||||
// Go to center
|
||||
ctx.lineTo(me._view.scaleZero.x, me._view.scaleZero.y);
|
||||
}
|
||||
}
|
||||
|
||||
ctx.save();
|
||||
var points = me._children.slice(); // clone array
|
||||
var lastDrawnIndex = -1;
|
||||
|
||||
// If we had points and want to fill this line, do so.
|
||||
if (me._children.length > 0 && vm.fill) {
|
||||
// Draw the background first (so the border is always on top)
|
||||
// If we are looping, adding the first point again
|
||||
if (loop && points.length) {
|
||||
points.push(points[0]);
|
||||
}
|
||||
|
||||
// Fill Line
|
||||
if (points.length && vm.fill) {
|
||||
ctx.beginPath();
|
||||
|
||||
helpers.each(me._children, function(point, index) {
|
||||
var previous = helpers.previousItem(me._children, index);
|
||||
var next = helpers.nextItem(me._children, index);
|
||||
for (var index = 0; index < points.length; ++index) {
|
||||
var current = points[index];
|
||||
var previous = helpers.previousItem(points, index);
|
||||
|
||||
var currentVM = current._view;
|
||||
|
||||
// First point moves to it's starting position no matter what
|
||||
if (index === 0) {
|
||||
if (me._loop) {
|
||||
ctx.moveTo(vm.scaleZero.x, vm.scaleZero.y);
|
||||
if (loop) {
|
||||
ctx.moveTo(scaleZero.x, scaleZero.y);
|
||||
} else {
|
||||
ctx.moveTo(point._view.x, vm.scaleZero);
|
||||
ctx.moveTo(currentVM.x, scaleZero);
|
||||
}
|
||||
|
||||
if (point._view.skip) {
|
||||
if (!me._loop) {
|
||||
ctx.moveTo(next._view.x, me._view.scaleZero);
|
||||
}
|
||||
} else {
|
||||
ctx.lineTo(point._view.x, point._view.y);
|
||||
if (!currentVM.skip) {
|
||||
lastDrawnIndex = index;
|
||||
ctx.lineTo(currentVM.x, currentVM.y);
|
||||
}
|
||||
} else {
|
||||
me.lineToNextPoint(previous, point, next, function(previousPoint, point, nextPoint) {
|
||||
if (me._loop) {
|
||||
// Go to center
|
||||
ctx.lineTo(me._view.scaleZero.x, me._view.scaleZero.y);
|
||||
} else {
|
||||
ctx.lineTo(previousPoint._view.x, me._view.scaleZero);
|
||||
ctx.moveTo(nextPoint._view.x, me._view.scaleZero);
|
||||
}
|
||||
}, function(previousPoint, point) {
|
||||
// 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);
|
||||
});
|
||||
}
|
||||
}, me);
|
||||
previous = lastDrawnIndex === -1 ? previous : points[lastDrawnIndex];
|
||||
|
||||
// For radial scales, loop back around to the first point
|
||||
if (me._loop) {
|
||||
loopBackToStart(true);
|
||||
} else {
|
||||
//Round off the line by going to the base of the chart, back to the start, then fill.
|
||||
ctx.lineTo(me._children[me._children.length - 1]._view.x, vm.scaleZero);
|
||||
ctx.lineTo(me._children[0]._view.x, vm.scaleZero);
|
||||
if (currentVM.skip) {
|
||||
// Only do this if this is the first point that is skipped
|
||||
if (!spanGaps && lastDrawnIndex === (index - 1)) {
|
||||
if (loop) {
|
||||
ctx.lineTo(scaleZero.x, scaleZero.y);
|
||||
} else {
|
||||
ctx.lineTo(previous._view.x, scaleZero);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (lastDrawnIndex !== (index - 1)) {
|
||||
// There was a gap and this is the first point after the gap. If we've never drawn a point, this is a special case.
|
||||
// If the first data point is NaN, then there is no real gap to skip
|
||||
if (spanGaps && lastDrawnIndex !== -1) {
|
||||
// We are spanning the gap, so simple draw a line to this point
|
||||
lineToPoint(previous, current)
|
||||
} else {
|
||||
if (loop) {
|
||||
ctx.lineTo(currentVM.x, currentVM.y);
|
||||
} else {
|
||||
ctx.lineTo(currentVM.x, scaleZero);
|
||||
ctx.lineTo(currentVM.x, currentVM.y);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Line to next point
|
||||
lineToPoint(previous, current);
|
||||
}
|
||||
lastDrawnIndex = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!loop) {
|
||||
ctx.lineTo(points[points.length - 1]._view.x, scaleZero);
|
||||
}
|
||||
|
||||
ctx.fillStyle = vm.backgroundColor || globalDefaults.defaultColor;
|
||||
@ -127,8 +124,8 @@ module.exports = function(Chart) {
|
||||
ctx.fill();
|
||||
}
|
||||
|
||||
// Stroke Line Options
|
||||
var globalOptionLineElements = globalDefaults.elements.line;
|
||||
// Now draw the line between all the points with any borders
|
||||
ctx.lineCap = vm.borderCapStyle || globalOptionLineElements.borderCapStyle;
|
||||
|
||||
// IE 9 and 10 do not support line dash
|
||||
@ -140,26 +137,38 @@ module.exports = function(Chart) {
|
||||
ctx.lineJoin = vm.borderJoinStyle || globalOptionLineElements.borderJoinStyle;
|
||||
ctx.lineWidth = vm.borderWidth || globalOptionLineElements.borderWidth;
|
||||
ctx.strokeStyle = vm.borderColor || globalDefaults.defaultColor;
|
||||
|
||||
// Stroke Line
|
||||
ctx.beginPath();
|
||||
lastDrawnIndex = -1;
|
||||
|
||||
helpers.each(me._children, function(point, index) {
|
||||
var previous = helpers.previousItem(me._children, index);
|
||||
var next = helpers.nextItem(me._children, index);
|
||||
for (var index = 0; index < points.length; ++index) {
|
||||
var current = points[index];
|
||||
var previous = helpers.previousItem(points, index);
|
||||
var currentVM = current._view;
|
||||
|
||||
// First point moves to it's starting position no matter what
|
||||
if (index === 0) {
|
||||
ctx.moveTo(point._view.x, point._view.y);
|
||||
if (currentVM.skip) {
|
||||
|
||||
} else {
|
||||
ctx.moveTo(currentVM.x, currentVM.y);
|
||||
lastDrawnIndex = index;
|
||||
}
|
||||
} else {
|
||||
me.lineToNextPoint(previous, point, next, function(previousPoint, point, nextPoint) {
|
||||
ctx.moveTo(nextPoint._view.x, nextPoint._view.y);
|
||||
}, function(previousPoint, point) {
|
||||
// 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);
|
||||
});
|
||||
}
|
||||
}, me);
|
||||
previous = lastDrawnIndex === -1 ? previous : points[lastDrawnIndex];
|
||||
|
||||
if (me._loop && me._children.length > 0) {
|
||||
loopBackToStart();
|
||||
if (!currentVM.skip) {
|
||||
if (lastDrawnIndex !== (index - 1) && !spanGaps) {
|
||||
// There was a gap and this is the first point after the gap
|
||||
ctx.moveTo(currentVM.x, currentVM.y);
|
||||
} else {
|
||||
// Line to next point
|
||||
lineToPoint(previous, current);
|
||||
}
|
||||
lastDrawnIndex = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx.stroke();
|
||||
|
||||
@ -126,6 +126,253 @@ describe('Line element tests', function() {
|
||||
}]);
|
||||
});
|
||||
|
||||
it('should draw with straight lines for a tension of 0', 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,
|
||||
tension: 0
|
||||
}
|
||||
}));
|
||||
points.push(new Chart.elements.Point({
|
||||
_datasetindex: 2,
|
||||
_index: 1,
|
||||
_view: {
|
||||
x: 5,
|
||||
y: 0,
|
||||
controlPointPreviousX: 5,
|
||||
controlPointPreviousY: 0,
|
||||
controlPointNextX: 5,
|
||||
controlPointNextY: 0,
|
||||
tension: 0
|
||||
}
|
||||
}));
|
||||
points.push(new Chart.elements.Point({
|
||||
_datasetindex: 2,
|
||||
_index: 2,
|
||||
_view: {
|
||||
x: 15,
|
||||
y: -10,
|
||||
controlPointPreviousX: 15,
|
||||
controlPointPreviousY: -10,
|
||||
controlPointNextX: 15,
|
||||
controlPointNextY: -10,
|
||||
tension: 0
|
||||
}
|
||||
}));
|
||||
points.push(new Chart.elements.Point({
|
||||
_datasetindex: 2,
|
||||
_index: 3,
|
||||
_view: {
|
||||
x: 19,
|
||||
y: -5,
|
||||
controlPointPreviousX: 19,
|
||||
controlPointPreviousY: -5,
|
||||
controlPointNextX: 19,
|
||||
controlPointNextY: -5,
|
||||
tension: 0
|
||||
}
|
||||
}));
|
||||
|
||||
var line = new Chart.elements.Line({
|
||||
_datasetindex: 2,
|
||||
_chart: {
|
||||
ctx: mockContext,
|
||||
},
|
||||
_children: points,
|
||||
// Need to provide some settings
|
||||
_view: {
|
||||
fill: false, // don't want to fill
|
||||
tension: 0.0, // no bezier curve for now
|
||||
scaleZero: 0
|
||||
}
|
||||
});
|
||||
|
||||
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: 'stroke',
|
||||
args: [],
|
||||
}, {
|
||||
name: 'restore',
|
||||
args: []
|
||||
}]);
|
||||
});
|
||||
|
||||
it('should draw stepped lines', 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,
|
||||
steppedLine: true
|
||||
}
|
||||
}));
|
||||
points.push(new Chart.elements.Point({
|
||||
_datasetindex: 2,
|
||||
_index: 1,
|
||||
_view: {
|
||||
x: 5,
|
||||
y: 0,
|
||||
controlPointPreviousX: 5,
|
||||
controlPointPreviousY: 0,
|
||||
controlPointNextX: 5,
|
||||
controlPointNextY: 0,
|
||||
steppedLine: true
|
||||
}
|
||||
}));
|
||||
points.push(new Chart.elements.Point({
|
||||
_datasetindex: 2,
|
||||
_index: 2,
|
||||
_view: {
|
||||
x: 15,
|
||||
y: -10,
|
||||
controlPointPreviousX: 15,
|
||||
controlPointPreviousY: -10,
|
||||
controlPointNextX: 15,
|
||||
controlPointNextY: -10,
|
||||
steppedLine: true
|
||||
}
|
||||
}));
|
||||
points.push(new Chart.elements.Point({
|
||||
_datasetindex: 2,
|
||||
_index: 3,
|
||||
_view: {
|
||||
x: 19,
|
||||
y: -5,
|
||||
controlPointPreviousX: 19,
|
||||
controlPointPreviousY: -5,
|
||||
controlPointNextX: 19,
|
||||
controlPointNextY: -5,
|
||||
steppedLine: true
|
||||
}
|
||||
}));
|
||||
|
||||
var line = new Chart.elements.Line({
|
||||
_datasetindex: 2,
|
||||
_chart: {
|
||||
ctx: mockContext,
|
||||
},
|
||||
_children: points,
|
||||
// Need to provide some settings
|
||||
_view: {
|
||||
fill: false, // don't want to fill
|
||||
tension: 0.0, // no bezier curve for now
|
||||
scaleZero: 0
|
||||
}
|
||||
});
|
||||
|
||||
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, 10]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [5, 0]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [15, 0]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [15, -10]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [19, -10]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [19, -5]
|
||||
}, {
|
||||
name: 'stroke',
|
||||
args: [],
|
||||
}, {
|
||||
name: 'restore',
|
||||
args: []
|
||||
}]);
|
||||
});
|
||||
|
||||
it('should draw with custom settings', function() {
|
||||
var mockContext = window.createMockContext();
|
||||
|
||||
@ -204,7 +451,7 @@ describe('Line element tests', function() {
|
||||
|
||||
var expected = [{
|
||||
name: 'save',
|
||||
args: [],
|
||||
args: []
|
||||
}, {
|
||||
name: 'beginPath',
|
||||
args: []
|
||||
@ -226,9 +473,6 @@ describe('Line element tests', function() {
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [19, 2]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [0, 2]
|
||||
}, {
|
||||
name: 'setFillStyle',
|
||||
args: ['rgb(0, 0, 0)']
|
||||
@ -275,7 +519,7 @@ describe('Line element tests', function() {
|
||||
args: [15, -10, 19, -5, 19, -5]
|
||||
}, {
|
||||
name: 'stroke',
|
||||
args: [],
|
||||
args: []
|
||||
}, {
|
||||
name: 'restore',
|
||||
args: []
|
||||
@ -283,7 +527,7 @@ describe('Line element tests', function() {
|
||||
expect(mockContext.getCalls()).toEqual(expected);
|
||||
});
|
||||
|
||||
it ('should skip points correctly', function() {
|
||||
it('should skip points correctly', function() {
|
||||
var mockContext = window.createMockContext();
|
||||
|
||||
// Create our points
|
||||
@ -368,20 +612,17 @@ describe('Line element tests', function() {
|
||||
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: [5, 2]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [0, 2]
|
||||
args: [19, 2]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [19, -5]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [19, 2]
|
||||
}, {
|
||||
name: 'setFillStyle',
|
||||
args: ['rgba(0,0,0,0.1)']
|
||||
@ -401,7 +642,7 @@ describe('Line element tests', function() {
|
||||
]
|
||||
}, {
|
||||
name: 'setLineDashOffset',
|
||||
args: [0.0]
|
||||
args: [0]
|
||||
}, {
|
||||
name: 'setLineJoin',
|
||||
args: ['miter']
|
||||
@ -421,14 +662,441 @@ describe('Line element tests', function() {
|
||||
name: 'bezierCurveTo',
|
||||
args: [0, 10, 5, 0, 5, 0]
|
||||
}, {
|
||||
name: 'moveTo',
|
||||
args: [19, -5]
|
||||
}, {
|
||||
name: 'moveTo',
|
||||
args: [19, -5]
|
||||
name: 'moveTo',
|
||||
args: [19, -5]
|
||||
}, {
|
||||
name: 'stroke',
|
||||
args: [],
|
||||
args: []
|
||||
}, {
|
||||
name: 'restore',
|
||||
args: []
|
||||
}];
|
||||
expect(mockContext.getCalls()).toEqual(expected);
|
||||
});
|
||||
|
||||
it('should skip points correctly when spanGaps is true', 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
|
||||
spanGaps: true
|
||||
}
|
||||
});
|
||||
|
||||
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: 'bezierCurveTo',
|
||||
args: [5, 0, 19, -5, 19, -5]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [19, 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]
|
||||
}, {
|
||||
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, 19, -5, 19, -5]
|
||||
}, {
|
||||
name: 'stroke',
|
||||
args: []
|
||||
}, {
|
||||
name: 'restore',
|
||||
args: []
|
||||
}];
|
||||
expect(mockContext.getCalls()).toEqual(expected);
|
||||
});
|
||||
|
||||
it('should skip the first point 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,
|
||||
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,
|
||||
// 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: [5, 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: [19, 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]
|
||||
}, {
|
||||
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: '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 the last point 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
|
||||
}
|
||||
}));
|
||||
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,
|
||||
// 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: 'bezierCurveTo',
|
||||
args: [5, 0, 15, -10, 15, -10]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [15, 2]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [19, 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]
|
||||
}, {
|
||||
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: 'stroke',
|
||||
args: []
|
||||
}, {
|
||||
name: 'restore',
|
||||
args: []
|
||||
@ -727,9 +1395,156 @@ describe('Line element tests', function() {
|
||||
}, {
|
||||
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 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.0, // no bezier curve for now
|
||||
scaleZero: {
|
||||
x: 3,
|
||||
y: 2
|
||||
},
|
||||
spanGaps: true
|
||||
}
|
||||
});
|
||||
|
||||
line.draw();
|
||||
|
||||
expect(mockContext.getCalls()).toEqual([{
|
||||
name: 'save',
|
||||
args: [],
|
||||
}, {
|
||||
name: 'beginPath',
|
||||
args: []
|
||||
}, {
|
||||
name: 'moveTo',
|
||||
args: [15, -10]
|
||||
args: [3, 2]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [0, 10]
|
||||
}, {
|
||||
name: 'bezierCurveTo',
|
||||
args: [0, 10, 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']
|
||||
}, {
|
||||
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, 15, -10, 15, -10]
|
||||
}, {
|
||||
name: 'bezierCurveTo',
|
||||
args: [15, -10, 19, -5, 19, -5]
|
||||
@ -873,9 +1688,6 @@ describe('Line element tests', function() {
|
||||
}, {
|
||||
name: 'beginPath',
|
||||
args: []
|
||||
}, {
|
||||
name: 'moveTo',
|
||||
args: [0, 10]
|
||||
}, {
|
||||
name: 'moveTo',
|
||||
args: [5, 0]
|
||||
@ -992,7 +1804,7 @@ describe('Line element tests', function() {
|
||||
args: [3, 2]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [3, 2]
|
||||
args: [0, 10]
|
||||
}, {
|
||||
name: 'setFillStyle',
|
||||
args: ['rgba(0,0,0,0.1)']
|
||||
@ -1036,7 +1848,7 @@ describe('Line element tests', function() {
|
||||
args: [5, 0, 15, -10, 15, -10]
|
||||
}, {
|
||||
name: 'moveTo',
|
||||
args: [19, -5]
|
||||
args: [0, 10]
|
||||
}, {
|
||||
name: 'stroke',
|
||||
args: [],
|
||||
@ -1045,4 +1857,4 @@ describe('Line element tests', function() {
|
||||
args: []
|
||||
}]);
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user