From 568f69e35a877bb3c171a55f127b1f346002a799 Mon Sep 17 00:00:00 2001 From: Larry Bordowitz Date: Thu, 15 Feb 2024 20:50:08 -0600 Subject: [PATCH] feat(Circle): Add counterclockwise parameter to Circle class --- CHANGELOG.md | 1 + src/shapes/Circle.ts | 33 +++++++++++++++++++++++---------- test/unit/circle.js | 9 +++++++++ 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9c06ea8bcd..fd70d51f128 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## [next] +- feat(Circle): Add counterclockwise parameter to Circle class [#9670](https://github.com/fabricjs/fabric.js/pull/9670) - feat(LayoutManager): Expose objects registration [#9661](https://github.com/fabricjs/fabric.js/pull/9661) - fix(Object): support specyfing toCanvasElement canvas [#9652](https://github.com/fabricjs/fabric.js/pull/9652) - ci(): no `src` imports [#9657](https://github.com/fabricjs/fabric.js/pull/9657) diff --git a/src/shapes/Circle.ts b/src/shapes/Circle.ts index cb233364800..99330946263 100644 --- a/src/shapes/Circle.ts +++ b/src/shapes/Circle.ts @@ -19,20 +19,25 @@ interface UniqueCircleProps { radius: number; /** - * degrees of start of the circle. - * probably will change to degrees in next major version - * @type Number 0 - 359 + * Angle for the start of the circle, in degrees. + * @type TDegree 0 - 359 * @default 0 */ startAngle: number; /** - * End angle of the circle - * probably will change to degrees in next major version - * @type Number 1 - 360 + * Angle for the end of the circle, in degrees + * @type TDegree 1 - 360 * @default 360 */ endAngle: number; + + /** + * Orientation for the direction of the circle. + * Setting to true will switch the arc of the circle to traverse from startAngle to endAngle in a counterclockwise direction, + * @default false + */ + counterclockwise: boolean; } export interface SerializedCircleProps @@ -41,12 +46,18 @@ export interface SerializedCircleProps export interface CircleProps extends FabricObjectProps, UniqueCircleProps {} -const CIRCLE_PROPS = ['radius', 'startAngle', 'endAngle'] as const; +const CIRCLE_PROPS = [ + 'radius', + 'startAngle', + 'endAngle', + 'counterclockwise', +] as const; export const circleDefaultValues: UniqueCircleProps = { radius: 0, startAngle: 0, endAngle: 360, + counterclockwise: true, }; export class Circle< @@ -60,6 +71,7 @@ export class Circle< declare radius: number; declare startAngle: number; declare endAngle: number; + declare counterclockwise: boolean; static type = 'Circle'; @@ -101,7 +113,7 @@ export class Circle< this.radius, degreesToRadians(this.startAngle), degreesToRadians(this.endAngle), - false + this.counterclockwise ); this._renderPaintInOrder(ctx); } @@ -169,12 +181,13 @@ export class Circle< startY = sin(start) * radius, endX = cos(end) * radius, endY = sin(end) * radius, - largeFlag = angle > 180 ? '1' : '0'; + largeFlag = angle > 180 ? '1' : '0', + sweepFlag = this.counterclockwise ? '0' : '1'; return [ `\n', 'half circle as clipPath'); }); + QUnit.test('toSVG with counterclockwise half circle', function (assert) { + var circle = new fabric.Circle({ width: 100, height: 100, radius: 10, endAngle: fabric.util.radiansToDegrees(Math.PI), counterclockwise: true }); + var svg = circle.toSVG(); + var svgClipPath = circle.toClipPathSVG(); + assert.equal(svg, '\n\n\n'); + assert.equal(svgClipPath, '\t\n', 'half circle as clipPath'); + }); + QUnit.test('fromElement', function(assert) { var done = assert.async(); assert.ok(typeof fabric.Circle.fromElement === 'function');