Merge pull request #19 from aha-app/issue-ellipse-translate-problem

Ellipse translate and rotate problem
This commit is contained in:
Zeno Zeng 2022-08-03 23:35:49 +08:00 committed by GitHub
commit b54e855632
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 71 additions and 8 deletions

View File

@ -1041,12 +1041,13 @@ export default (function () {
return;
}
x = this.__matrixTransform(x, y).x;
y = this.__matrixTransform(x, y).y;
var scaleX = Math.hypot(this.__transformMatrix.a, this.__transformMatrix.b);
var scaleY = Math.hypot(this.__transformMatrix.c, this.__transformMatrix.d);
radiusX = radiusX * scaleX;
radiusY = radiusY * scaleY;
var transformedCenter = this.__matrixTransform(x, y);
x = transformedCenter.x;
y = transformedCenter.y;
var scale = this.__getTransformScale();
radiusX = radiusX * scale.x;
radiusY = radiusY * scale.y;
rotation = rotation + this.__getTransformRotation()
startAngle = startAngle % (2*Math.PI);
endAngle = endAngle % (2*Math.PI);
@ -1074,8 +1075,14 @@ export default (function () {
} else {
largeArcFlag = diff > Math.PI ? 1 : 0;
}
this.lineTo(startX / scaleX, startY / scaleY);
// Transform is already applied, so temporarily remove since lineTo
// will apply it again.
var currentTransform = this.__transformMatrix;
this.resetTransform();
this.lineTo(startX, startY);
this.__transformMatrix = currentTransform;
this.__addPathCommand(format("A {rx} {ry} {xAxisRotation} {largeArcFlag} {sweepFlag} {endX} {endY}",
{
rx:radiusX,
@ -1335,6 +1342,25 @@ export default (function () {
return new DOMPoint(x, y).matrixTransform(this.__transformMatrix)
}
/**
*
* @returns The scale component of the transform matrix as {x,y}.
*/
Context.prototype.__getTransformScale = function() {
return {
x: Math.hypot(this.__transformMatrix.a, this.__transformMatrix.b),
y: Math.hypot(this.__transformMatrix.c, this.__transformMatrix.d)
};
}
/**
*
* @returns The rotation component of the transform matrix in radians.
*/
Context.prototype.__getTransformRotation = function() {
return Math.atan2(this.__transformMatrix.b, this.__transformMatrix.a);
}
/**
*
* @param {*} sx The x-axis coordinate of the top-left corner of the rectangle from which the ImageData will be extracted.

View File

@ -5,6 +5,7 @@ import arcTo2 from './tests/arcTo2'
import arcToScaled from './tests/arcToScaled'
import emptyArc from './tests/emptyArc'
import ellipse from './tests/ellipse'
import ellipse2 from './tests/ellipse2'
import fillstyle from './tests/fillstyle'
import globalAlpha from './tests/globalalpha'
import gradient from './tests/gradient'
@ -27,6 +28,7 @@ const tests = [
arcToScaled,
emptyArc,
ellipse,
ellipse2,
fillstyle,
globalAlpha,
gradient,

View File

@ -6,6 +6,7 @@ import arcTo2 from './tests/arcTo2'
import arcToScaled from './tests/arcToScaled'
import emptyArc from './tests/emptyArc'
import ellipse from './tests/ellipse'
import ellipse2 from './tests/ellipse2'
import fillstyle from './tests/fillstyle'
import globalAlpha from './tests/globalalpha'
import gradient from './tests/gradient'
@ -28,6 +29,7 @@ const tests = {
arcToScaled,
emptyArc,
ellipse,
ellipse2,
fillstyle,
globalAlpha,
gradient,

33
test/tests/ellipse2.js Normal file
View File

@ -0,0 +1,33 @@
export default function ellipse2(ctx) {
// Draw a cylinder using ellipses and lines.
var w = 100, h = 100, rx = 50, ry = 10;
var scaleX = 1.5, scaleY = 1.2;
ctx.rotate(Math.PI / 10);
ctx.scale(scaleX, scaleY);
ctx.translate(200, 25);
ctx.beginPath();
ctx.moveTo(-w / 2, -h / 2 + ry);
// upper arc top
ctx.ellipse(0, -h / 2 + ry, rx, ry, Math.PI, 0, Math.PI, 0);
ctx.moveTo(-w / 2, -h / 2 + ry);
// upper arc bottom
ctx.ellipse(0, -h / 2 + ry, rx, ry, Math.PI, 0, Math.PI, 1);
ctx.moveTo(-w / 2, -h / 2 + ry);
// left line
ctx.lineTo(-w / 2, + h / 2 - ry);
// lower arc
ctx.ellipse(0, h / 2 - ry, rx, ry, Math.PI, 0, Math.PI, 1);
// right line
ctx.lineTo(w / 2, -h / 2 + ry);
ctx.moveTo(-w / 2, -h / 2 + ry);
ctx.closePath();
// Remove scale before stroking because the SVG conversion is not correctly
// scaling the stroke as well. Without this the pixel differences are too
// high.
ctx.resetTransform();
ctx.stroke();
};