From 5e9add1f6d1b9815f3c24294b1eea2682f111101 Mon Sep 17 00:00:00 2001 From: ChepteaCatalin <71984989+ChepteaCatalin@users.noreply.github.com> Date: Sat, 23 Sep 2023 11:58:54 +0300 Subject: [PATCH] feat(matrix): allow rotating relative to a point different than the origin. close #1033 --- src/core/matrix.ts | 11 ++++++++--- src/tool/parseSVG.ts | 5 ++++- test/ut/spec/core/matrix.test.ts | 21 +++++++++++++++++++++ 3 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 test/ut/spec/core/matrix.test.ts diff --git a/src/core/matrix.ts b/src/core/matrix.ts index 78009f815..13b5b9e19 100644 --- a/src/core/matrix.ts +++ b/src/core/matrix.ts @@ -79,7 +79,12 @@ export function translate(out: MatrixArray, a: MatrixArray, v: VectorArray): Mat /** * 旋转变换 */ -export function rotate(out: MatrixArray, a: MatrixArray, rad: number): MatrixArray { +export function rotate( + out: MatrixArray, + a: MatrixArray, + rad: number, + pivot: VectorArray = [0, 0] +): MatrixArray { const aa = a[0]; const ac = a[2]; const atx = a[4]; @@ -93,8 +98,8 @@ export function rotate(out: MatrixArray, a: MatrixArray, rad: number): MatrixArr out[1] = -aa * st + ab * ct; out[2] = ac * ct + ad * st; out[3] = -ac * st + ct * ad; - out[4] = ct * atx + st * aty; - out[5] = ct * aty - st * atx; + out[4] = ct * (atx - pivot[0]) + st * (aty - pivot[1]) + pivot[0]; + out[5] = ct * (aty - pivot[1]) - st * (atx - pivot[0]) + pivot[1]; return out; } diff --git a/src/tool/parseSVG.ts b/src/tool/parseSVG.ts index cbcc2a804..0ee2739a6 100644 --- a/src/tool/parseSVG.ts +++ b/src/tool/parseSVG.ts @@ -845,7 +845,10 @@ function parseTransformAttribute(xmlNode: SVGElement, node: Element): void { break; case 'rotate': // TODO: zrender use different hand in coordinate system. - matrix.rotate(mt, mt, -parseFloat(valueArr[0]) * DEGREE_TO_ANGLE); + matrix.rotate(mt, mt, -parseFloat(valueArr[0]) * DEGREE_TO_ANGLE, [ + parseFloat(valueArr[1] || '0'), + parseFloat(valueArr[2] || '0') + ]); break; case 'skewX': const sx = Math.tan(parseFloat(valueArr[0]) * DEGREE_TO_ANGLE); diff --git a/test/ut/spec/core/matrix.test.ts b/test/ut/spec/core/matrix.test.ts new file mode 100644 index 000000000..e3c609d74 --- /dev/null +++ b/test/ut/spec/core/matrix.test.ts @@ -0,0 +1,21 @@ +import { rotate } from '../../../../src/core/matrix'; + +describe('matrix', function () { + it('should rotate relative to a pivot point', function () { + const matrix = [ + 0.9659258262890683, 0.25881904510252074, -0.25881904510252074, 0.9659258262890683, + 40.213201392710246, -26.96358986452364 + ]; + const rad = -0.2617993877991494; + const pivot = [122.511, 139.243]; + + const result = rotate(matrix, matrix, rad, pivot); + + expect(result[0]).toBeCloseTo(0.8660254037844387, 5); + expect(result[1]).toBeCloseTo(0.49999999999999994, 5); + expect(result[2]).toBeCloseTo(-0.49999999999999994, 5); + expect(result[3]).toBeCloseTo(0.8660254037844387, 5); + expect(result[4]).toBeCloseTo(86.03486175696463, 5); + expect(result[5]).toBeCloseTo(-42.600475299156585, 5); + }); +});