Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent bezier points from being capped when a data point is off the chart #5937

Merged
merged 3 commits into from Jan 5, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 10 additions & 4 deletions src/controllers/controller.line.js
Expand Up @@ -281,10 +281,16 @@ module.exports = DatasetController.extend({
if (me.chart.options.elements.line.capBezierPoints) {
for (i = 0, ilen = points.length; i < ilen; ++i) {
model = points[i]._model;
model.controlPointPreviousX = capControlPoint(model.controlPointPreviousX, area.left, area.right);
model.controlPointPreviousY = capControlPoint(model.controlPointPreviousY, area.top, area.bottom);
model.controlPointNextX = capControlPoint(model.controlPointNextX, area.left, area.right);
model.controlPointNextY = capControlPoint(model.controlPointNextY, area.top, area.bottom);
if (helpers.canvas.isPointInArea(model, area)) {
nagix marked this conversation as resolved.
Show resolved Hide resolved
if (i > 0 && helpers.canvas.isPointInArea(points[i - 1]._model, area)) {
model.controlPointPreviousX = capControlPoint(model.controlPointPreviousX, area.left, area.right);
model.controlPointPreviousY = capControlPoint(model.controlPointPreviousY, area.top, area.bottom);
}
if (i < points.length - 1 && helpers.canvas.isPointInArea(points[i + 1]._model, area)) {
model.controlPointNextX = capControlPoint(model.controlPointNextX, area.left, area.right);
model.controlPointNextY = capControlPoint(model.controlPointNextY, area.top, area.bottom);
}
}
}
}
},
Expand Down
4 changes: 1 addition & 3 deletions src/elements/element.point.js
Expand Up @@ -65,14 +65,12 @@ module.exports = Element.extend({

draw: function(chartArea) {
var vm = this._view;
var model = this._model;
var ctx = this._chart.ctx;
var pointStyle = vm.pointStyle;
var rotation = vm.rotation;
var radius = vm.radius;
var x = vm.x;
var y = vm.y;
var epsilon = 0.0000001; // 0.0000001 is margin in pixels for Accumulated error.
var globalDefaults = defaults.global;
var defaultColor = globalDefaults.defaultColor; // eslint-disable-line no-shadow

Expand All @@ -81,7 +79,7 @@ module.exports = Element.extend({
}

// Clipping for Points.
if (chartArea === undefined || (model.x > chartArea.left - epsilon && chartArea.right + epsilon > model.x && model.y > chartArea.top - epsilon && chartArea.bottom + epsilon > model.y)) {
if (chartArea === undefined || helpers.canvas.isPointInArea(vm, chartArea)) {
ctx.strokeStyle = vm.borderColor || defaultColor;
ctx.lineWidth = helpers.valueOrDefault(vm.borderWidth, globalDefaults.elements.point.borderWidth);
ctx.fillStyle = vm.backgroundColor || defaultColor;
Expand Down
7 changes: 7 additions & 0 deletions src/helpers/helpers.canvas.js
Expand Up @@ -172,6 +172,13 @@ var exports = {
ctx.stroke();
},

isPointInArea: function(point, area) {
nagix marked this conversation as resolved.
Show resolved Hide resolved
var epsilon = 1e-6; // 1e-6 is margin in pixels for Accumulated error.

return point.x > area.left - epsilon && point.x < area.right + epsilon &&
point.y > area.top - epsilon && point.y < area.bottom + epsilon;
},

clipArea: function(ctx, area) {
ctx.save();
ctx.beginPath();
Expand Down
14 changes: 14 additions & 0 deletions test/specs/helpers.canvas.tests.js
Expand Up @@ -86,4 +86,18 @@ describe('Chart.helpers.canvas', function() {
expect(context.getCalls()).toEqual([{name: 'rect', args: [10, 20, 30, 40]}]);
});
});

describe('isPointInArea', function() {
it('should determine if a point is in the area', function() {
var isPointInArea = helpers.canvas.isPointInArea;
var area = {left: 0, top: 0, right: 512, bottom: 256};

expect(isPointInArea({x: 0, y: 0}, area)).toBe(true);
expect(isPointInArea({x: -1e-12, y: -1e-12}, area)).toBe(true);
expect(isPointInArea({x: 512, y: 256}, area)).toBe(true);
expect(isPointInArea({x: 512 + 1e-12, y: 256 + 1e-12}, area)).toBe(true);
expect(isPointInArea({x: -1e-3, y: 0}, area)).toBe(false);
expect(isPointInArea({x: 0, y: 256 + 1e-3}, area)).toBe(false);
});
});
});