Skip to content

Commit

Permalink
Adjust the size of rectRounded/rectRot point to fit pointRadius
Browse files Browse the repository at this point in the history
- Calculate the vertices of the shapes so that they are inscribed in the circle that has the radius of `pointRadius`
- Remove `translate()` and `rotate()` to fix the regression introduced by chartjs#5319
  • Loading branch information
nagix committed Nov 23, 2018
1 parent f6d9a39 commit 53f3ae4
Show file tree
Hide file tree
Showing 9 changed files with 312 additions and 68 deletions.
122 changes: 67 additions & 55 deletions src/helpers/helpers.canvas.js
Expand Up @@ -2,6 +2,12 @@

var helpers = require('./helpers.core');

var RAD_PER_DEG = Math.PI / 180;
var DOUBLE_PI = Math.PI * 2;
var HALF_PI = Math.PI / 2;
var QUARTER_PI = Math.PI / 4;
var TWO_THIRDS_PI = Math.PI * 2 / 3;

/**
* @namespace Chart.helpers.canvas
*/
Expand Down Expand Up @@ -49,8 +55,8 @@ var exports = module.exports = {
},

drawPoint: function(ctx, style, radius, x, y, rotation) {
var type, edgeLength, xOffset, yOffset, height, size;
rotation = rotation || 0;
var type, xOffset, yOffset, size, cornerRadius;
var rad = (rotation || 0) * RAD_PER_DEG;

if (style && typeof style === 'object') {
type = style.toString();
Expand All @@ -64,88 +70,94 @@ var exports = module.exports = {
return;
}

ctx.save();
ctx.translate(x, y);
ctx.rotate(rotation * Math.PI / 180);
ctx.beginPath();

switch (style) {
// Default includes circle
default:
ctx.arc(0, 0, radius, 0, Math.PI * 2);
ctx.arc(x, y, radius, 0, DOUBLE_PI);
ctx.closePath();
break;
case 'triangle':
edgeLength = 3 * radius / Math.sqrt(3);
height = edgeLength * Math.sqrt(3) / 2;
ctx.moveTo(-edgeLength / 2, height / 3);
ctx.lineTo(edgeLength / 2, height / 3);
ctx.lineTo(0, -2 * height / 3);
ctx.moveTo(x + Math.sin(rad) * radius, y - Math.cos(rad) * radius);
rad += TWO_THIRDS_PI;
ctx.lineTo(x + Math.sin(rad) * radius, y - Math.cos(rad) * radius);
rad += TWO_THIRDS_PI;
ctx.lineTo(x + Math.sin(rad) * radius, y - Math.cos(rad) * radius);
ctx.closePath();
break;
case 'rect':
size = 1 / Math.SQRT2 * radius;
ctx.rect(-size, -size, 2 * size, 2 * size);
break;
case 'rectRounded':
var offset = radius / Math.SQRT2;
var leftX = -offset;
var topY = -offset;
var sideSize = Math.SQRT2 * radius;

// NOTE(SB) the rounded rect implementation changed to use `arcTo`
// NOTE(SB) the rounded rect implementation changed to use `arc`
// instead of `quadraticCurveTo` since it generates better results
// when rect is almost a circle. 0.425 (instead of 0.5) produces
// when rect is almost a circle. 0.516 (instead of 0.5) produces
// results visually closer to the previous impl.
this.roundedRect(ctx, leftX, topY, sideSize, sideSize, radius * 0.425);
cornerRadius = radius * 0.516;
size = radius - cornerRadius;
xOffset = Math.cos(rad + QUARTER_PI) * size;
yOffset = Math.sin(rad + QUARTER_PI) * size;
ctx.arc(x - xOffset, y - yOffset, cornerRadius, rad - Math.PI, rad - HALF_PI);
ctx.arc(x + yOffset, y - xOffset, cornerRadius, rad - HALF_PI, rad);
ctx.arc(x + xOffset, y + yOffset, cornerRadius, rad, rad + HALF_PI);
ctx.arc(x - yOffset, y + xOffset, cornerRadius, rad + HALF_PI, rad + Math.PI);
ctx.closePath();
break;
case 'rect':
if (!rotation) {
size = Math.SQRT1_2 * radius;
ctx.rect(x - size, y - size, 2 * size, 2 * size);
break;
}
rad += QUARTER_PI;
/* falls through */
case 'rectRot':
size = 1 / Math.SQRT2 * radius;
ctx.moveTo(-size, 0);
ctx.lineTo(0, size);
ctx.lineTo(size, 0);
ctx.lineTo(0, -size);
xOffset = Math.cos(rad) * radius;
yOffset = Math.sin(rad) * radius;
ctx.moveTo(x - xOffset, y - yOffset);
ctx.lineTo(x + yOffset, y - xOffset);
ctx.lineTo(x + xOffset, y + yOffset);
ctx.lineTo(x - yOffset, y + xOffset);
ctx.closePath();
break;
case 'cross':
ctx.moveTo(0, radius);
ctx.lineTo(0, -radius);
ctx.moveTo(-radius, 0);
ctx.lineTo(radius, 0);
break;
case 'crossRot':
xOffset = Math.cos(Math.PI / 4) * radius;
yOffset = Math.sin(Math.PI / 4) * radius;
ctx.moveTo(-xOffset, -yOffset);
ctx.lineTo(xOffset, yOffset);
ctx.moveTo(-xOffset, yOffset);
ctx.lineTo(xOffset, -yOffset);
rad += QUARTER_PI;
/* falls through */
case 'cross':
xOffset = Math.cos(rad) * radius;
yOffset = Math.sin(rad) * radius;
ctx.moveTo(x - xOffset, y - yOffset);
ctx.lineTo(x + xOffset, y + yOffset);
ctx.moveTo(x + yOffset, y - xOffset);
ctx.lineTo(x - yOffset, y + xOffset);
break;
case 'star':
ctx.moveTo(0, radius);
ctx.lineTo(0, -radius);
ctx.moveTo(-radius, 0);
ctx.lineTo(radius, 0);
xOffset = Math.cos(Math.PI / 4) * radius;
yOffset = Math.sin(Math.PI / 4) * radius;
ctx.moveTo(-xOffset, -yOffset);
ctx.lineTo(xOffset, yOffset);
ctx.moveTo(-xOffset, yOffset);
ctx.lineTo(xOffset, -yOffset);
xOffset = Math.cos(rad) * radius;
yOffset = Math.sin(rad) * radius;
ctx.moveTo(x - xOffset, y - yOffset);
ctx.lineTo(x + xOffset, y + yOffset);
ctx.moveTo(x + yOffset, y - xOffset);
ctx.lineTo(x - yOffset, y + xOffset);
rad += QUARTER_PI;
xOffset = Math.cos(rad) * radius;
yOffset = Math.sin(rad) * radius;
ctx.moveTo(x - xOffset, y - yOffset);
ctx.lineTo(x + xOffset, y + yOffset);
ctx.moveTo(x + yOffset, y - xOffset);
ctx.lineTo(x - yOffset, y + xOffset);
break;
case 'line':
ctx.moveTo(-radius, 0);
ctx.lineTo(radius, 0);
xOffset = Math.cos(rad) * radius;
yOffset = Math.sin(rad) * radius;
ctx.moveTo(x - xOffset, y - yOffset);
ctx.lineTo(x + xOffset, y + yOffset);
break;
case 'dash':
ctx.moveTo(0, 0);
ctx.lineTo(radius, 0);
ctx.moveTo(x, y);
ctx.lineTo(x + Math.cos(rad) * radius, y + Math.sin(rad) * radius);
break;
}

ctx.fill();
ctx.stroke();
ctx.restore();
},

clipArea: function(ctx, area) {
Expand Down
Binary file modified test/fixtures/controller.bubble/point-style.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/fixtures/controller.line/point-style.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/fixtures/controller.radar/point-style.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/fixtures/element.point/point-style-rect-rot.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/fixtures/element.point/point-style-rect-rounded.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 53f3ae4

Please sign in to comment.