From cbc3be9be40a577bc73818f80a12aa67a327722a Mon Sep 17 00:00:00 2001 From: tony chen Date: Wed, 6 Nov 2024 13:13:26 +0800 Subject: [PATCH] fix: draw circle --- src/skia/SkiaPathRebuilder.ts | 46 +++++++++++++++++++++++++---------- src/skia/helper.ts | 4 +++ 2 files changed, 37 insertions(+), 13 deletions(-) create mode 100644 src/skia/helper.ts diff --git a/src/skia/SkiaPathRebuilder.ts b/src/skia/SkiaPathRebuilder.ts index f1039741..84d20816 100644 --- a/src/skia/SkiaPathRebuilder.ts +++ b/src/skia/SkiaPathRebuilder.ts @@ -1,6 +1,9 @@ import { PathRebuilder } from 'zrender/lib/core/PathProxy'; import { SkPath, Skia } from '@shopify/react-native-skia'; +import { isAroundZero } from './helper'; +const PI = Math.PI; +const PI2 = Math.PI * 2; export default class SkiaPathRebuilder implements PathRebuilder { private path: SkPath; @@ -50,24 +53,41 @@ export default class SkiaPathRebuilder implements PathRebuilder { rotation: number, startAngle: number, endAngle: number, - counterclockwise: boolean = false + anticlockwise: boolean = false ) { - const useSmallArc = Math.abs(endAngle - startAngle) <= Math.PI; + let dTheta = endAngle - startAngle; + const clockwise = !anticlockwise; + + const dThetaPositive = Math.abs(dTheta); + const isCircle = + isAroundZero(dThetaPositive - PI2) || + (clockwise ? dTheta >= PI2 : -dTheta >= PI2); + + const useSmallArc = Math.abs(endAngle - startAngle) <= PI; const endX = x + radiusX * Math.cos(endAngle); const endY = y + radiusY * Math.sin(endAngle); - const xAxisRotateInDegrees = (rotation * 180) / Math.PI; - - this.path.arcToRotated( - radiusX, - radiusY, - xAxisRotateInDegrees, - useSmallArc, - counterclockwise, - endX, - endY - ); + const xAxisRotateInDegrees = (rotation * 180) / PI; + if (isCircle) { + const ovalRect = { + x: x - radiusX, + y: y - radiusY, + width: radiusX * 2, + height: radiusY * 2, + }; + this.path.addOval(ovalRect, anticlockwise); + } else { + this.path.arcToRotated( + radiusX, + radiusY, + xAxisRotateInDegrees, + useSmallArc, + anticlockwise, + endX, + endY + ); + } } rect(x: number, y: number, width: number, height: number): void { diff --git a/src/skia/helper.ts b/src/skia/helper.ts new file mode 100644 index 00000000..9e313a2d --- /dev/null +++ b/src/skia/helper.ts @@ -0,0 +1,4 @@ +const EPSILON = 1e-4; +export function isAroundZero(transform: number) { + return transform < EPSILON && transform > -EPSILON; +} \ No newline at end of file