modern-path2d 1.7.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +316 -11
- package/dist/index.d.cts +122 -2
- package/dist/index.d.mts +122 -2
- package/dist/index.d.ts +122 -2
- package/dist/index.js +3 -2
- package/dist/index.mjs +313 -12
- package/package.json +3 -2
package/dist/index.d.cts
CHANGED
|
@@ -249,6 +249,20 @@ declare class Transform2D {
|
|
|
249
249
|
destroy(): void;
|
|
250
250
|
}
|
|
251
251
|
|
|
252
|
+
type BooleanOp = 'union' | 'intersection' | 'difference' | 'xor';
|
|
253
|
+
/**
|
|
254
|
+
* A flat ring: `[x0, y0, x1, y1, …]` (the same layout {@link Curve.getAdaptiveVertices} produces).
|
|
255
|
+
* A path is described as an array of such rings (one per sub-path).
|
|
256
|
+
*/
|
|
257
|
+
type FlatRing = number[];
|
|
258
|
+
/**
|
|
259
|
+
* Boolean operation between two ring soups, returning the result as flat rings (shells wound
|
|
260
|
+
* counter-clockwise, holes clockwise — so a nonzero fill renders them correctly). Powered by the
|
|
261
|
+
* Martinez–Rueda sweep-line clipper (`polygon-clipping`); because the inputs are sampled outlines,
|
|
262
|
+
* the result is a polygonal approximation of curved paths.
|
|
263
|
+
*/
|
|
264
|
+
declare function polygonBoolean(op: BooleanOp, ringsA: FlatRing[], ringsB: FlatRing[]): FlatRing[];
|
|
265
|
+
|
|
252
266
|
declare function catmullRom(t: number, p0: number, p1: number, p2: number, p3: number): number;
|
|
253
267
|
|
|
254
268
|
interface CssFunctionArg {
|
|
@@ -375,6 +389,12 @@ interface LineStyle {
|
|
|
375
389
|
cap: LineCap;
|
|
376
390
|
miterLimit: number;
|
|
377
391
|
}
|
|
392
|
+
/**
|
|
393
|
+
* Derive a triangulator {@link LineStyle} from a (partial) {@link Path2DStyle}. This is what
|
|
394
|
+
* makes `path.strokeTriangulate()` honor `style.strokeWidth` / `strokeLinejoin` / `strokeLinecap`
|
|
395
|
+
* / `strokeMiterlimit` instead of silently falling back to a 1px miter hairline.
|
|
396
|
+
*/
|
|
397
|
+
declare function resolveLineStyle(style?: Partial<Path2DStyle>): LineStyle;
|
|
378
398
|
declare function strokeTriangulate(points: number[], options?: StrokeTriangulateOptions): StrokeTriangulatedResult;
|
|
379
399
|
|
|
380
400
|
interface IsPointInFillOptions {
|
|
@@ -413,6 +433,13 @@ declare abstract class Curve {
|
|
|
413
433
|
getPointAt(u: number, output?: Vector2): Vector2;
|
|
414
434
|
isClockwise(): boolean;
|
|
415
435
|
getControlPointRefs(): Vector2[];
|
|
436
|
+
/**
|
|
437
|
+
* Reverse the traversal direction in place (start ↔ end, same geometry). The base
|
|
438
|
+
* implementation reverses the order of the control-point *values*, which is correct for
|
|
439
|
+
* line / Bézier / spline primitives whose {@link getControlPointRefs} order matches their
|
|
440
|
+
* parametric order. {@link RoundCurve} (angle-based) and composites (child order) override it.
|
|
441
|
+
*/
|
|
442
|
+
reverse(): this;
|
|
416
443
|
applyTransform(transform: Transform2D | ((point: Vector2) => void)): this;
|
|
417
444
|
getUnevenVertices(count?: number, output?: number[]): number[];
|
|
418
445
|
getSpacedVertices(count?: number, output?: number[]): number[];
|
|
@@ -428,6 +455,16 @@ declare abstract class Curve {
|
|
|
428
455
|
getUToTMapping(u: number, distance?: number): number;
|
|
429
456
|
getTangent(t: number, output?: Vector2): Vector2;
|
|
430
457
|
getTangentAt(u: number, output?: Vector2): Vector2;
|
|
458
|
+
/**
|
|
459
|
+
* PathKit-style sample at an absolute arc-length `distance` along the curve: the point, the unit
|
|
460
|
+
* tangent, and the tangent `angle` in radians. `distance` is clamped to `[0, getLength()]`, so
|
|
461
|
+
* passing `0`/`getLength()` always yields the endpoints. See {@link PathMeasure} for a wrapper.
|
|
462
|
+
*/
|
|
463
|
+
getPosTan(distance: number): {
|
|
464
|
+
position: Vector2;
|
|
465
|
+
tangent: Vector2;
|
|
466
|
+
angle: number;
|
|
467
|
+
};
|
|
431
468
|
getNormal(t: number, output?: Vector2): Vector2;
|
|
432
469
|
getNormalAt(u: number, output?: Vector2): Vector2;
|
|
433
470
|
getTForPoint(target: Vector2Like, epsilon?: number): number;
|
|
@@ -464,6 +501,13 @@ declare abstract class Curve {
|
|
|
464
501
|
contains(x: number, y: number, options?: IsPointInFillOptions): boolean;
|
|
465
502
|
getFillVertices(_options?: FillTriangulateOptions): number[];
|
|
466
503
|
fillTriangulate(options?: FillTriangulateOptions): FillTriangulatedResult;
|
|
504
|
+
/**
|
|
505
|
+
* Whether this curve forms a closed loop (its outline should be stroked without end caps,
|
|
506
|
+
* stitching the last vertex back to the first). The base test is purely geometric — the first
|
|
507
|
+
* sampled vertex coincides with the last. Curves that close without a duplicated endpoint
|
|
508
|
+
* (a full-revolution {@link RoundCurve}, rectangles, polygons) override this.
|
|
509
|
+
*/
|
|
510
|
+
isClosed(): boolean;
|
|
467
511
|
strokeTriangulate(options?: StrokeTriangulateOptions): StrokeTriangulatedResult;
|
|
468
512
|
toCommands(): Path2DCommand[];
|
|
469
513
|
toData(): Path2DData;
|
|
@@ -494,6 +538,13 @@ declare class RoundCurve extends Curve {
|
|
|
494
538
|
set dy(val: number);
|
|
495
539
|
constructor(_center?: Vector2, _radius?: Vector2, _diff?: Vector2, rotate?: number, startAngle?: number, endAngle?: number, clockwise?: boolean);
|
|
496
540
|
isClockwise(): boolean;
|
|
541
|
+
/**
|
|
542
|
+
* A circle/ellipse arc is closed when it sweeps (at least) a full revolution — the sampled
|
|
543
|
+
* outline does not duplicate the start vertex, so the geometric first==last test in the base
|
|
544
|
+
* class would wrongly report a full circle as open and leave a seam gap in the stroke.
|
|
545
|
+
*/
|
|
546
|
+
isClosed(): boolean;
|
|
547
|
+
reverse(): this;
|
|
497
548
|
protected _getDeltaAngle(): number;
|
|
498
549
|
getPoint(t: number, output?: Vector2): Vector2;
|
|
499
550
|
/**
|
|
@@ -541,7 +592,14 @@ declare class CompositeCurve<T extends Curve = Curve> extends Curve {
|
|
|
541
592
|
protected _removeNextPointIfEqualPrevPoint(output: number[], offset: number): number[];
|
|
542
593
|
getSpacedVertices(count?: number, output?: number[]): number[];
|
|
543
594
|
getAdaptiveVertices(output?: number[]): number[];
|
|
595
|
+
/**
|
|
596
|
+
* A composite is closed when its single child is closed (e.g. a lone full-circle arc), or when
|
|
597
|
+
* its assembled outline returns to its start (rectangles, polygons, multi-segment loops).
|
|
598
|
+
*/
|
|
599
|
+
isClosed(): boolean;
|
|
544
600
|
strokeTriangulate(options?: StrokeTriangulateOptions): StrokeTriangulatedResult;
|
|
601
|
+
/** Reverse the sub-curve order and reverse each sub-curve, so the whole outline runs backwards. */
|
|
602
|
+
reverse(): this;
|
|
545
603
|
getFillVertices(options?: FillTriangulateOptions): number[];
|
|
546
604
|
applyTransform(transform: Transform2D | ((point: Vector2) => void)): this;
|
|
547
605
|
getMinMax(min?: Vector2, max?: Vector2): {
|
|
@@ -564,6 +622,7 @@ declare class CubicBezierCurve extends Curve {
|
|
|
564
622
|
getPoint(t: number, output?: Vector2): Vector2;
|
|
565
623
|
getAdaptiveVertices(output?: number[]): number[];
|
|
566
624
|
getControlPointRefs(): Vector2[];
|
|
625
|
+
reverse(): this;
|
|
567
626
|
protected _solveQuadratic(a: number, b: number, c: number): number[];
|
|
568
627
|
getMinMax(min?: Vector2, max?: Vector2): {
|
|
569
628
|
min: Vector2;
|
|
@@ -589,6 +648,7 @@ declare class LineCurve extends Curve {
|
|
|
589
648
|
getTangent(_t: number, output?: Vector2): Vector2;
|
|
590
649
|
getTangentAt(u: number, output?: Vector2): Vector2;
|
|
591
650
|
getControlPointRefs(): Vector2[];
|
|
651
|
+
reverse(): this;
|
|
592
652
|
getAdaptiveVertices(output?: number[]): number[];
|
|
593
653
|
getMinMax(min?: Vector2, max?: Vector2): {
|
|
594
654
|
min: Vector2;
|
|
@@ -621,6 +681,7 @@ declare class QuadraticBezierCurve extends Curve {
|
|
|
621
681
|
constructor(p1?: Vector2, cp?: Vector2, p2?: Vector2);
|
|
622
682
|
getPoint(t: number, output?: Vector2): Vector2;
|
|
623
683
|
getControlPointRefs(): Vector2[];
|
|
684
|
+
reverse(): this;
|
|
624
685
|
getAdaptiveVertices(output?: number[]): number[];
|
|
625
686
|
getMinMax(min?: Vector2, max?: Vector2): {
|
|
626
687
|
min: Vector2;
|
|
@@ -665,6 +726,7 @@ declare class SplineCurve extends Curve {
|
|
|
665
726
|
constructor(points?: Vector2[]);
|
|
666
727
|
getPoint(t: number, output?: Vector2): Vector2;
|
|
667
728
|
getControlPointRefs(): Vector2[];
|
|
729
|
+
reverse(): this;
|
|
668
730
|
copyFrom(source: SplineCurve): this;
|
|
669
731
|
}
|
|
670
732
|
|
|
@@ -676,6 +738,13 @@ declare class CurvePath extends CompositeCurve {
|
|
|
676
738
|
addPoints(points: Vector2[]): this;
|
|
677
739
|
addCommands(commands: Path2DCommand[]): this;
|
|
678
740
|
addData(data: string): this;
|
|
741
|
+
/**
|
|
742
|
+
* A sub-path is closed if it was explicitly closed (`autoClose`, i.e. a `Z`/`closePath`), or if
|
|
743
|
+
* it forms a geometric loop / wraps a single closed primitive (handled by the base class).
|
|
744
|
+
*/
|
|
745
|
+
isClosed(): boolean;
|
|
746
|
+
/** Reverse direction, then refresh the {@link startPoint}/{@link currentPoint} cursors. */
|
|
747
|
+
reverse(): this;
|
|
679
748
|
protected _closeVertices(output: number[]): number[];
|
|
680
749
|
getUnevenVertices(count?: number, output?: number[]): number[];
|
|
681
750
|
getSpacedVertices(count?: number, output?: number[]): number[];
|
|
@@ -760,6 +829,23 @@ declare class Path2D<T = any> extends CompositeCurve<CurvePath> {
|
|
|
760
829
|
/** Per-sub-path sampled rings, cached for repeated hit tests. */
|
|
761
830
|
protected _getRings(): number[][];
|
|
762
831
|
isPointInFill(point: Vector2Like, options?: IsPointInFillOptions): boolean;
|
|
832
|
+
/** Build a `Path2D` from flat rings (`[x0,y0,…]` per sub-path); closed-and-filled as sub-paths. */
|
|
833
|
+
static fromRings(rings: number[][], style?: Partial<Path2DStyle>): Path2D;
|
|
834
|
+
/**
|
|
835
|
+
* Boolean (path) operation against another path, returning a NEW `Path2D` whose outline is the
|
|
836
|
+
* polygonal result. Curves are sampled before clipping, so the result is a polygonal
|
|
837
|
+
* approximation (see {@link polygonBoolean}). The result inherits this path's `style` unless
|
|
838
|
+
* overridden via `style`. Holes are emitted as oppositely-wound sub-paths (nonzero fill).
|
|
839
|
+
*/
|
|
840
|
+
booleanOp(op: BooleanOp, other: Path2D, style?: Partial<Path2DStyle>): Path2D;
|
|
841
|
+
/** `this ∪ other` — the combined filled area. */
|
|
842
|
+
union(other: Path2D, style?: Partial<Path2DStyle>): Path2D;
|
|
843
|
+
/** `this ∩ other` — only the overlapping area. */
|
|
844
|
+
intersection(other: Path2D, style?: Partial<Path2DStyle>): Path2D;
|
|
845
|
+
/** `this − other` — this path with `other` cut away. */
|
|
846
|
+
difference(other: Path2D, style?: Partial<Path2DStyle>): Path2D;
|
|
847
|
+
/** `this ⊕ other` — areas covered by exactly one of the two paths. */
|
|
848
|
+
xor(other: Path2D, style?: Partial<Path2DStyle>): Path2D;
|
|
763
849
|
/**
|
|
764
850
|
* Test whether a point lies on this path's stroke. A hit on any sub-path counts.
|
|
765
851
|
*
|
|
@@ -833,6 +919,40 @@ declare class Path2DSet<T = any> {
|
|
|
833
919
|
}>): HTMLCanvasElement;
|
|
834
920
|
}
|
|
835
921
|
|
|
922
|
+
interface PosTan {
|
|
923
|
+
position: Vector2;
|
|
924
|
+
tangent: Vector2;
|
|
925
|
+
angle: number;
|
|
926
|
+
}
|
|
927
|
+
/**
|
|
928
|
+
* PathKit/Skia-style arc-length measurement over any {@link Curve} (including `CurvePath` and
|
|
929
|
+
* `Path2D`). Wraps the curve's existing arc-length cache, so repeated queries are cheap.
|
|
930
|
+
*
|
|
931
|
+
* ```ts
|
|
932
|
+
* const measure = new PathMeasure(path)
|
|
933
|
+
* const { position, angle } = measure.getPosTan(measure.getLength() * progress)
|
|
934
|
+
* ```
|
|
935
|
+
*/
|
|
936
|
+
declare class PathMeasure {
|
|
937
|
+
curve: Curve;
|
|
938
|
+
constructor(curve: Curve);
|
|
939
|
+
/** Total arc length of the path. */
|
|
940
|
+
getLength(): number;
|
|
941
|
+
/** Whether the path forms a closed loop (see {@link Curve.isClosed}). */
|
|
942
|
+
isClosed(): boolean;
|
|
943
|
+
/** Point + unit tangent + tangent angle at an absolute arc-length `distance` (clamped). */
|
|
944
|
+
getPosTan(distance: number): PosTan;
|
|
945
|
+
/** Point at an absolute arc-length `distance` (clamped to `[0, getLength()]`). */
|
|
946
|
+
getPosition(distance: number): Vector2;
|
|
947
|
+
/** Point + tangent at a normalized progress `t ∈ [0, 1]` along the path. */
|
|
948
|
+
getPosTanAtProgress(t: number): PosTan;
|
|
949
|
+
/**
|
|
950
|
+
* Evenly sample the path into `count + 1` {@link PosTan} entries (arc-length spaced), e.g. to
|
|
951
|
+
* lay glyphs along a path or drive an `animate(progress)`-style traversal.
|
|
952
|
+
*/
|
|
953
|
+
sample(count?: number): PosTan[];
|
|
954
|
+
}
|
|
955
|
+
|
|
836
956
|
declare class FFDControlGrid {
|
|
837
957
|
rows: number;
|
|
838
958
|
cols: number;
|
|
@@ -875,5 +995,5 @@ declare function svgToDom(svg: string | SVGElement): SVGElement;
|
|
|
875
995
|
|
|
876
996
|
declare function svgToPath2DSet(svg: string | SVGElement): Path2DSet;
|
|
877
997
|
|
|
878
|
-
export { ArcCurve, BoundingBox, CompositeCurve, CubicBezierCurve, Curve, CurvePath, EllipseCurve, EquilateralPolygonCurve, FFDControlGrid, LineCurve, PI, PI_2, Path2D, Path2DSet, PolygonCurve, QuadraticBezierCurve, RectangleCurve, RoundRectangleCurve, SplineCurve, Transform2D, Vector2, applyFFD, catmullRom, cubicBezier, drawPoint, fillTriangulate, getAdaptiveCubicBezierCurvePoints, getAdaptiveQuadraticBezierCurvePoints, getDirectedArea, getIntersectionPoint, nonzeroFillRule, parseArcCommand, parseCssArg, parseCssArgs, parseCssFunctions, parsePathDataArgs, pointInPolygon, pointInPolygons, pointToPolylineDistance, pointToSegmentDistance, quadraticBezier, setCanvasContext, strokeTriangulate, svgPathCommandsAddToPath2D, svgPathCommandsToData, svgPathDataToCommands, svgToDom, svgToPath2DSet, toKebabCase };
|
|
879
|
-
export type { CssFunction, CssFunctionArg, DrawPointOptions, FillRule, FillTriangulateOptions, FillTriangulatedResult, IsPointInFillOptions, IsPointInStrokeOptions, LineCap, LineJoin, LineStyle, ParseCssFunctionContext, Path2DCommand, Path2DData, Path2DDrawStyle, Path2DStyle, StrokeLinecap, StrokeLinejoin, StrokeTriangulateOptions, StrokeTriangulatedResult, TransformableObject, TriangulatedResult, Vector2Like };
|
|
998
|
+
export { ArcCurve, BoundingBox, CompositeCurve, CubicBezierCurve, Curve, CurvePath, EllipseCurve, EquilateralPolygonCurve, FFDControlGrid, LineCurve, PI, PI_2, Path2D, Path2DSet, PathMeasure, PolygonCurve, QuadraticBezierCurve, RectangleCurve, RoundRectangleCurve, SplineCurve, Transform2D, Vector2, applyFFD, catmullRom, cubicBezier, drawPoint, fillTriangulate, getAdaptiveCubicBezierCurvePoints, getAdaptiveQuadraticBezierCurvePoints, getDirectedArea, getIntersectionPoint, nonzeroFillRule, parseArcCommand, parseCssArg, parseCssArgs, parseCssFunctions, parsePathDataArgs, pointInPolygon, pointInPolygons, pointToPolylineDistance, pointToSegmentDistance, polygonBoolean, quadraticBezier, resolveLineStyle, setCanvasContext, strokeTriangulate, svgPathCommandsAddToPath2D, svgPathCommandsToData, svgPathDataToCommands, svgToDom, svgToPath2DSet, toKebabCase };
|
|
999
|
+
export type { BooleanOp, CssFunction, CssFunctionArg, DrawPointOptions, FillRule, FillTriangulateOptions, FillTriangulatedResult, FlatRing, IsPointInFillOptions, IsPointInStrokeOptions, LineCap, LineJoin, LineStyle, ParseCssFunctionContext, Path2DCommand, Path2DData, Path2DDrawStyle, Path2DStyle, PosTan, StrokeLinecap, StrokeLinejoin, StrokeTriangulateOptions, StrokeTriangulatedResult, TransformableObject, TriangulatedResult, Vector2Like };
|
package/dist/index.d.mts
CHANGED
|
@@ -249,6 +249,20 @@ declare class Transform2D {
|
|
|
249
249
|
destroy(): void;
|
|
250
250
|
}
|
|
251
251
|
|
|
252
|
+
type BooleanOp = 'union' | 'intersection' | 'difference' | 'xor';
|
|
253
|
+
/**
|
|
254
|
+
* A flat ring: `[x0, y0, x1, y1, …]` (the same layout {@link Curve.getAdaptiveVertices} produces).
|
|
255
|
+
* A path is described as an array of such rings (one per sub-path).
|
|
256
|
+
*/
|
|
257
|
+
type FlatRing = number[];
|
|
258
|
+
/**
|
|
259
|
+
* Boolean operation between two ring soups, returning the result as flat rings (shells wound
|
|
260
|
+
* counter-clockwise, holes clockwise — so a nonzero fill renders them correctly). Powered by the
|
|
261
|
+
* Martinez–Rueda sweep-line clipper (`polygon-clipping`); because the inputs are sampled outlines,
|
|
262
|
+
* the result is a polygonal approximation of curved paths.
|
|
263
|
+
*/
|
|
264
|
+
declare function polygonBoolean(op: BooleanOp, ringsA: FlatRing[], ringsB: FlatRing[]): FlatRing[];
|
|
265
|
+
|
|
252
266
|
declare function catmullRom(t: number, p0: number, p1: number, p2: number, p3: number): number;
|
|
253
267
|
|
|
254
268
|
interface CssFunctionArg {
|
|
@@ -375,6 +389,12 @@ interface LineStyle {
|
|
|
375
389
|
cap: LineCap;
|
|
376
390
|
miterLimit: number;
|
|
377
391
|
}
|
|
392
|
+
/**
|
|
393
|
+
* Derive a triangulator {@link LineStyle} from a (partial) {@link Path2DStyle}. This is what
|
|
394
|
+
* makes `path.strokeTriangulate()` honor `style.strokeWidth` / `strokeLinejoin` / `strokeLinecap`
|
|
395
|
+
* / `strokeMiterlimit` instead of silently falling back to a 1px miter hairline.
|
|
396
|
+
*/
|
|
397
|
+
declare function resolveLineStyle(style?: Partial<Path2DStyle>): LineStyle;
|
|
378
398
|
declare function strokeTriangulate(points: number[], options?: StrokeTriangulateOptions): StrokeTriangulatedResult;
|
|
379
399
|
|
|
380
400
|
interface IsPointInFillOptions {
|
|
@@ -413,6 +433,13 @@ declare abstract class Curve {
|
|
|
413
433
|
getPointAt(u: number, output?: Vector2): Vector2;
|
|
414
434
|
isClockwise(): boolean;
|
|
415
435
|
getControlPointRefs(): Vector2[];
|
|
436
|
+
/**
|
|
437
|
+
* Reverse the traversal direction in place (start ↔ end, same geometry). The base
|
|
438
|
+
* implementation reverses the order of the control-point *values*, which is correct for
|
|
439
|
+
* line / Bézier / spline primitives whose {@link getControlPointRefs} order matches their
|
|
440
|
+
* parametric order. {@link RoundCurve} (angle-based) and composites (child order) override it.
|
|
441
|
+
*/
|
|
442
|
+
reverse(): this;
|
|
416
443
|
applyTransform(transform: Transform2D | ((point: Vector2) => void)): this;
|
|
417
444
|
getUnevenVertices(count?: number, output?: number[]): number[];
|
|
418
445
|
getSpacedVertices(count?: number, output?: number[]): number[];
|
|
@@ -428,6 +455,16 @@ declare abstract class Curve {
|
|
|
428
455
|
getUToTMapping(u: number, distance?: number): number;
|
|
429
456
|
getTangent(t: number, output?: Vector2): Vector2;
|
|
430
457
|
getTangentAt(u: number, output?: Vector2): Vector2;
|
|
458
|
+
/**
|
|
459
|
+
* PathKit-style sample at an absolute arc-length `distance` along the curve: the point, the unit
|
|
460
|
+
* tangent, and the tangent `angle` in radians. `distance` is clamped to `[0, getLength()]`, so
|
|
461
|
+
* passing `0`/`getLength()` always yields the endpoints. See {@link PathMeasure} for a wrapper.
|
|
462
|
+
*/
|
|
463
|
+
getPosTan(distance: number): {
|
|
464
|
+
position: Vector2;
|
|
465
|
+
tangent: Vector2;
|
|
466
|
+
angle: number;
|
|
467
|
+
};
|
|
431
468
|
getNormal(t: number, output?: Vector2): Vector2;
|
|
432
469
|
getNormalAt(u: number, output?: Vector2): Vector2;
|
|
433
470
|
getTForPoint(target: Vector2Like, epsilon?: number): number;
|
|
@@ -464,6 +501,13 @@ declare abstract class Curve {
|
|
|
464
501
|
contains(x: number, y: number, options?: IsPointInFillOptions): boolean;
|
|
465
502
|
getFillVertices(_options?: FillTriangulateOptions): number[];
|
|
466
503
|
fillTriangulate(options?: FillTriangulateOptions): FillTriangulatedResult;
|
|
504
|
+
/**
|
|
505
|
+
* Whether this curve forms a closed loop (its outline should be stroked without end caps,
|
|
506
|
+
* stitching the last vertex back to the first). The base test is purely geometric — the first
|
|
507
|
+
* sampled vertex coincides with the last. Curves that close without a duplicated endpoint
|
|
508
|
+
* (a full-revolution {@link RoundCurve}, rectangles, polygons) override this.
|
|
509
|
+
*/
|
|
510
|
+
isClosed(): boolean;
|
|
467
511
|
strokeTriangulate(options?: StrokeTriangulateOptions): StrokeTriangulatedResult;
|
|
468
512
|
toCommands(): Path2DCommand[];
|
|
469
513
|
toData(): Path2DData;
|
|
@@ -494,6 +538,13 @@ declare class RoundCurve extends Curve {
|
|
|
494
538
|
set dy(val: number);
|
|
495
539
|
constructor(_center?: Vector2, _radius?: Vector2, _diff?: Vector2, rotate?: number, startAngle?: number, endAngle?: number, clockwise?: boolean);
|
|
496
540
|
isClockwise(): boolean;
|
|
541
|
+
/**
|
|
542
|
+
* A circle/ellipse arc is closed when it sweeps (at least) a full revolution — the sampled
|
|
543
|
+
* outline does not duplicate the start vertex, so the geometric first==last test in the base
|
|
544
|
+
* class would wrongly report a full circle as open and leave a seam gap in the stroke.
|
|
545
|
+
*/
|
|
546
|
+
isClosed(): boolean;
|
|
547
|
+
reverse(): this;
|
|
497
548
|
protected _getDeltaAngle(): number;
|
|
498
549
|
getPoint(t: number, output?: Vector2): Vector2;
|
|
499
550
|
/**
|
|
@@ -541,7 +592,14 @@ declare class CompositeCurve<T extends Curve = Curve> extends Curve {
|
|
|
541
592
|
protected _removeNextPointIfEqualPrevPoint(output: number[], offset: number): number[];
|
|
542
593
|
getSpacedVertices(count?: number, output?: number[]): number[];
|
|
543
594
|
getAdaptiveVertices(output?: number[]): number[];
|
|
595
|
+
/**
|
|
596
|
+
* A composite is closed when its single child is closed (e.g. a lone full-circle arc), or when
|
|
597
|
+
* its assembled outline returns to its start (rectangles, polygons, multi-segment loops).
|
|
598
|
+
*/
|
|
599
|
+
isClosed(): boolean;
|
|
544
600
|
strokeTriangulate(options?: StrokeTriangulateOptions): StrokeTriangulatedResult;
|
|
601
|
+
/** Reverse the sub-curve order and reverse each sub-curve, so the whole outline runs backwards. */
|
|
602
|
+
reverse(): this;
|
|
545
603
|
getFillVertices(options?: FillTriangulateOptions): number[];
|
|
546
604
|
applyTransform(transform: Transform2D | ((point: Vector2) => void)): this;
|
|
547
605
|
getMinMax(min?: Vector2, max?: Vector2): {
|
|
@@ -564,6 +622,7 @@ declare class CubicBezierCurve extends Curve {
|
|
|
564
622
|
getPoint(t: number, output?: Vector2): Vector2;
|
|
565
623
|
getAdaptiveVertices(output?: number[]): number[];
|
|
566
624
|
getControlPointRefs(): Vector2[];
|
|
625
|
+
reverse(): this;
|
|
567
626
|
protected _solveQuadratic(a: number, b: number, c: number): number[];
|
|
568
627
|
getMinMax(min?: Vector2, max?: Vector2): {
|
|
569
628
|
min: Vector2;
|
|
@@ -589,6 +648,7 @@ declare class LineCurve extends Curve {
|
|
|
589
648
|
getTangent(_t: number, output?: Vector2): Vector2;
|
|
590
649
|
getTangentAt(u: number, output?: Vector2): Vector2;
|
|
591
650
|
getControlPointRefs(): Vector2[];
|
|
651
|
+
reverse(): this;
|
|
592
652
|
getAdaptiveVertices(output?: number[]): number[];
|
|
593
653
|
getMinMax(min?: Vector2, max?: Vector2): {
|
|
594
654
|
min: Vector2;
|
|
@@ -621,6 +681,7 @@ declare class QuadraticBezierCurve extends Curve {
|
|
|
621
681
|
constructor(p1?: Vector2, cp?: Vector2, p2?: Vector2);
|
|
622
682
|
getPoint(t: number, output?: Vector2): Vector2;
|
|
623
683
|
getControlPointRefs(): Vector2[];
|
|
684
|
+
reverse(): this;
|
|
624
685
|
getAdaptiveVertices(output?: number[]): number[];
|
|
625
686
|
getMinMax(min?: Vector2, max?: Vector2): {
|
|
626
687
|
min: Vector2;
|
|
@@ -665,6 +726,7 @@ declare class SplineCurve extends Curve {
|
|
|
665
726
|
constructor(points?: Vector2[]);
|
|
666
727
|
getPoint(t: number, output?: Vector2): Vector2;
|
|
667
728
|
getControlPointRefs(): Vector2[];
|
|
729
|
+
reverse(): this;
|
|
668
730
|
copyFrom(source: SplineCurve): this;
|
|
669
731
|
}
|
|
670
732
|
|
|
@@ -676,6 +738,13 @@ declare class CurvePath extends CompositeCurve {
|
|
|
676
738
|
addPoints(points: Vector2[]): this;
|
|
677
739
|
addCommands(commands: Path2DCommand[]): this;
|
|
678
740
|
addData(data: string): this;
|
|
741
|
+
/**
|
|
742
|
+
* A sub-path is closed if it was explicitly closed (`autoClose`, i.e. a `Z`/`closePath`), or if
|
|
743
|
+
* it forms a geometric loop / wraps a single closed primitive (handled by the base class).
|
|
744
|
+
*/
|
|
745
|
+
isClosed(): boolean;
|
|
746
|
+
/** Reverse direction, then refresh the {@link startPoint}/{@link currentPoint} cursors. */
|
|
747
|
+
reverse(): this;
|
|
679
748
|
protected _closeVertices(output: number[]): number[];
|
|
680
749
|
getUnevenVertices(count?: number, output?: number[]): number[];
|
|
681
750
|
getSpacedVertices(count?: number, output?: number[]): number[];
|
|
@@ -760,6 +829,23 @@ declare class Path2D<T = any> extends CompositeCurve<CurvePath> {
|
|
|
760
829
|
/** Per-sub-path sampled rings, cached for repeated hit tests. */
|
|
761
830
|
protected _getRings(): number[][];
|
|
762
831
|
isPointInFill(point: Vector2Like, options?: IsPointInFillOptions): boolean;
|
|
832
|
+
/** Build a `Path2D` from flat rings (`[x0,y0,…]` per sub-path); closed-and-filled as sub-paths. */
|
|
833
|
+
static fromRings(rings: number[][], style?: Partial<Path2DStyle>): Path2D;
|
|
834
|
+
/**
|
|
835
|
+
* Boolean (path) operation against another path, returning a NEW `Path2D` whose outline is the
|
|
836
|
+
* polygonal result. Curves are sampled before clipping, so the result is a polygonal
|
|
837
|
+
* approximation (see {@link polygonBoolean}). The result inherits this path's `style` unless
|
|
838
|
+
* overridden via `style`. Holes are emitted as oppositely-wound sub-paths (nonzero fill).
|
|
839
|
+
*/
|
|
840
|
+
booleanOp(op: BooleanOp, other: Path2D, style?: Partial<Path2DStyle>): Path2D;
|
|
841
|
+
/** `this ∪ other` — the combined filled area. */
|
|
842
|
+
union(other: Path2D, style?: Partial<Path2DStyle>): Path2D;
|
|
843
|
+
/** `this ∩ other` — only the overlapping area. */
|
|
844
|
+
intersection(other: Path2D, style?: Partial<Path2DStyle>): Path2D;
|
|
845
|
+
/** `this − other` — this path with `other` cut away. */
|
|
846
|
+
difference(other: Path2D, style?: Partial<Path2DStyle>): Path2D;
|
|
847
|
+
/** `this ⊕ other` — areas covered by exactly one of the two paths. */
|
|
848
|
+
xor(other: Path2D, style?: Partial<Path2DStyle>): Path2D;
|
|
763
849
|
/**
|
|
764
850
|
* Test whether a point lies on this path's stroke. A hit on any sub-path counts.
|
|
765
851
|
*
|
|
@@ -833,6 +919,40 @@ declare class Path2DSet<T = any> {
|
|
|
833
919
|
}>): HTMLCanvasElement;
|
|
834
920
|
}
|
|
835
921
|
|
|
922
|
+
interface PosTan {
|
|
923
|
+
position: Vector2;
|
|
924
|
+
tangent: Vector2;
|
|
925
|
+
angle: number;
|
|
926
|
+
}
|
|
927
|
+
/**
|
|
928
|
+
* PathKit/Skia-style arc-length measurement over any {@link Curve} (including `CurvePath` and
|
|
929
|
+
* `Path2D`). Wraps the curve's existing arc-length cache, so repeated queries are cheap.
|
|
930
|
+
*
|
|
931
|
+
* ```ts
|
|
932
|
+
* const measure = new PathMeasure(path)
|
|
933
|
+
* const { position, angle } = measure.getPosTan(measure.getLength() * progress)
|
|
934
|
+
* ```
|
|
935
|
+
*/
|
|
936
|
+
declare class PathMeasure {
|
|
937
|
+
curve: Curve;
|
|
938
|
+
constructor(curve: Curve);
|
|
939
|
+
/** Total arc length of the path. */
|
|
940
|
+
getLength(): number;
|
|
941
|
+
/** Whether the path forms a closed loop (see {@link Curve.isClosed}). */
|
|
942
|
+
isClosed(): boolean;
|
|
943
|
+
/** Point + unit tangent + tangent angle at an absolute arc-length `distance` (clamped). */
|
|
944
|
+
getPosTan(distance: number): PosTan;
|
|
945
|
+
/** Point at an absolute arc-length `distance` (clamped to `[0, getLength()]`). */
|
|
946
|
+
getPosition(distance: number): Vector2;
|
|
947
|
+
/** Point + tangent at a normalized progress `t ∈ [0, 1]` along the path. */
|
|
948
|
+
getPosTanAtProgress(t: number): PosTan;
|
|
949
|
+
/**
|
|
950
|
+
* Evenly sample the path into `count + 1` {@link PosTan} entries (arc-length spaced), e.g. to
|
|
951
|
+
* lay glyphs along a path or drive an `animate(progress)`-style traversal.
|
|
952
|
+
*/
|
|
953
|
+
sample(count?: number): PosTan[];
|
|
954
|
+
}
|
|
955
|
+
|
|
836
956
|
declare class FFDControlGrid {
|
|
837
957
|
rows: number;
|
|
838
958
|
cols: number;
|
|
@@ -875,5 +995,5 @@ declare function svgToDom(svg: string | SVGElement): SVGElement;
|
|
|
875
995
|
|
|
876
996
|
declare function svgToPath2DSet(svg: string | SVGElement): Path2DSet;
|
|
877
997
|
|
|
878
|
-
export { ArcCurve, BoundingBox, CompositeCurve, CubicBezierCurve, Curve, CurvePath, EllipseCurve, EquilateralPolygonCurve, FFDControlGrid, LineCurve, PI, PI_2, Path2D, Path2DSet, PolygonCurve, QuadraticBezierCurve, RectangleCurve, RoundRectangleCurve, SplineCurve, Transform2D, Vector2, applyFFD, catmullRom, cubicBezier, drawPoint, fillTriangulate, getAdaptiveCubicBezierCurvePoints, getAdaptiveQuadraticBezierCurvePoints, getDirectedArea, getIntersectionPoint, nonzeroFillRule, parseArcCommand, parseCssArg, parseCssArgs, parseCssFunctions, parsePathDataArgs, pointInPolygon, pointInPolygons, pointToPolylineDistance, pointToSegmentDistance, quadraticBezier, setCanvasContext, strokeTriangulate, svgPathCommandsAddToPath2D, svgPathCommandsToData, svgPathDataToCommands, svgToDom, svgToPath2DSet, toKebabCase };
|
|
879
|
-
export type { CssFunction, CssFunctionArg, DrawPointOptions, FillRule, FillTriangulateOptions, FillTriangulatedResult, IsPointInFillOptions, IsPointInStrokeOptions, LineCap, LineJoin, LineStyle, ParseCssFunctionContext, Path2DCommand, Path2DData, Path2DDrawStyle, Path2DStyle, StrokeLinecap, StrokeLinejoin, StrokeTriangulateOptions, StrokeTriangulatedResult, TransformableObject, TriangulatedResult, Vector2Like };
|
|
998
|
+
export { ArcCurve, BoundingBox, CompositeCurve, CubicBezierCurve, Curve, CurvePath, EllipseCurve, EquilateralPolygonCurve, FFDControlGrid, LineCurve, PI, PI_2, Path2D, Path2DSet, PathMeasure, PolygonCurve, QuadraticBezierCurve, RectangleCurve, RoundRectangleCurve, SplineCurve, Transform2D, Vector2, applyFFD, catmullRom, cubicBezier, drawPoint, fillTriangulate, getAdaptiveCubicBezierCurvePoints, getAdaptiveQuadraticBezierCurvePoints, getDirectedArea, getIntersectionPoint, nonzeroFillRule, parseArcCommand, parseCssArg, parseCssArgs, parseCssFunctions, parsePathDataArgs, pointInPolygon, pointInPolygons, pointToPolylineDistance, pointToSegmentDistance, polygonBoolean, quadraticBezier, resolveLineStyle, setCanvasContext, strokeTriangulate, svgPathCommandsAddToPath2D, svgPathCommandsToData, svgPathDataToCommands, svgToDom, svgToPath2DSet, toKebabCase };
|
|
999
|
+
export type { BooleanOp, CssFunction, CssFunctionArg, DrawPointOptions, FillRule, FillTriangulateOptions, FillTriangulatedResult, FlatRing, IsPointInFillOptions, IsPointInStrokeOptions, LineCap, LineJoin, LineStyle, ParseCssFunctionContext, Path2DCommand, Path2DData, Path2DDrawStyle, Path2DStyle, PosTan, StrokeLinecap, StrokeLinejoin, StrokeTriangulateOptions, StrokeTriangulatedResult, TransformableObject, TriangulatedResult, Vector2Like };
|
package/dist/index.d.ts
CHANGED
|
@@ -249,6 +249,20 @@ declare class Transform2D {
|
|
|
249
249
|
destroy(): void;
|
|
250
250
|
}
|
|
251
251
|
|
|
252
|
+
type BooleanOp = 'union' | 'intersection' | 'difference' | 'xor';
|
|
253
|
+
/**
|
|
254
|
+
* A flat ring: `[x0, y0, x1, y1, …]` (the same layout {@link Curve.getAdaptiveVertices} produces).
|
|
255
|
+
* A path is described as an array of such rings (one per sub-path).
|
|
256
|
+
*/
|
|
257
|
+
type FlatRing = number[];
|
|
258
|
+
/**
|
|
259
|
+
* Boolean operation between two ring soups, returning the result as flat rings (shells wound
|
|
260
|
+
* counter-clockwise, holes clockwise — so a nonzero fill renders them correctly). Powered by the
|
|
261
|
+
* Martinez–Rueda sweep-line clipper (`polygon-clipping`); because the inputs are sampled outlines,
|
|
262
|
+
* the result is a polygonal approximation of curved paths.
|
|
263
|
+
*/
|
|
264
|
+
declare function polygonBoolean(op: BooleanOp, ringsA: FlatRing[], ringsB: FlatRing[]): FlatRing[];
|
|
265
|
+
|
|
252
266
|
declare function catmullRom(t: number, p0: number, p1: number, p2: number, p3: number): number;
|
|
253
267
|
|
|
254
268
|
interface CssFunctionArg {
|
|
@@ -375,6 +389,12 @@ interface LineStyle {
|
|
|
375
389
|
cap: LineCap;
|
|
376
390
|
miterLimit: number;
|
|
377
391
|
}
|
|
392
|
+
/**
|
|
393
|
+
* Derive a triangulator {@link LineStyle} from a (partial) {@link Path2DStyle}. This is what
|
|
394
|
+
* makes `path.strokeTriangulate()` honor `style.strokeWidth` / `strokeLinejoin` / `strokeLinecap`
|
|
395
|
+
* / `strokeMiterlimit` instead of silently falling back to a 1px miter hairline.
|
|
396
|
+
*/
|
|
397
|
+
declare function resolveLineStyle(style?: Partial<Path2DStyle>): LineStyle;
|
|
378
398
|
declare function strokeTriangulate(points: number[], options?: StrokeTriangulateOptions): StrokeTriangulatedResult;
|
|
379
399
|
|
|
380
400
|
interface IsPointInFillOptions {
|
|
@@ -413,6 +433,13 @@ declare abstract class Curve {
|
|
|
413
433
|
getPointAt(u: number, output?: Vector2): Vector2;
|
|
414
434
|
isClockwise(): boolean;
|
|
415
435
|
getControlPointRefs(): Vector2[];
|
|
436
|
+
/**
|
|
437
|
+
* Reverse the traversal direction in place (start ↔ end, same geometry). The base
|
|
438
|
+
* implementation reverses the order of the control-point *values*, which is correct for
|
|
439
|
+
* line / Bézier / spline primitives whose {@link getControlPointRefs} order matches their
|
|
440
|
+
* parametric order. {@link RoundCurve} (angle-based) and composites (child order) override it.
|
|
441
|
+
*/
|
|
442
|
+
reverse(): this;
|
|
416
443
|
applyTransform(transform: Transform2D | ((point: Vector2) => void)): this;
|
|
417
444
|
getUnevenVertices(count?: number, output?: number[]): number[];
|
|
418
445
|
getSpacedVertices(count?: number, output?: number[]): number[];
|
|
@@ -428,6 +455,16 @@ declare abstract class Curve {
|
|
|
428
455
|
getUToTMapping(u: number, distance?: number): number;
|
|
429
456
|
getTangent(t: number, output?: Vector2): Vector2;
|
|
430
457
|
getTangentAt(u: number, output?: Vector2): Vector2;
|
|
458
|
+
/**
|
|
459
|
+
* PathKit-style sample at an absolute arc-length `distance` along the curve: the point, the unit
|
|
460
|
+
* tangent, and the tangent `angle` in radians. `distance` is clamped to `[0, getLength()]`, so
|
|
461
|
+
* passing `0`/`getLength()` always yields the endpoints. See {@link PathMeasure} for a wrapper.
|
|
462
|
+
*/
|
|
463
|
+
getPosTan(distance: number): {
|
|
464
|
+
position: Vector2;
|
|
465
|
+
tangent: Vector2;
|
|
466
|
+
angle: number;
|
|
467
|
+
};
|
|
431
468
|
getNormal(t: number, output?: Vector2): Vector2;
|
|
432
469
|
getNormalAt(u: number, output?: Vector2): Vector2;
|
|
433
470
|
getTForPoint(target: Vector2Like, epsilon?: number): number;
|
|
@@ -464,6 +501,13 @@ declare abstract class Curve {
|
|
|
464
501
|
contains(x: number, y: number, options?: IsPointInFillOptions): boolean;
|
|
465
502
|
getFillVertices(_options?: FillTriangulateOptions): number[];
|
|
466
503
|
fillTriangulate(options?: FillTriangulateOptions): FillTriangulatedResult;
|
|
504
|
+
/**
|
|
505
|
+
* Whether this curve forms a closed loop (its outline should be stroked without end caps,
|
|
506
|
+
* stitching the last vertex back to the first). The base test is purely geometric — the first
|
|
507
|
+
* sampled vertex coincides with the last. Curves that close without a duplicated endpoint
|
|
508
|
+
* (a full-revolution {@link RoundCurve}, rectangles, polygons) override this.
|
|
509
|
+
*/
|
|
510
|
+
isClosed(): boolean;
|
|
467
511
|
strokeTriangulate(options?: StrokeTriangulateOptions): StrokeTriangulatedResult;
|
|
468
512
|
toCommands(): Path2DCommand[];
|
|
469
513
|
toData(): Path2DData;
|
|
@@ -494,6 +538,13 @@ declare class RoundCurve extends Curve {
|
|
|
494
538
|
set dy(val: number);
|
|
495
539
|
constructor(_center?: Vector2, _radius?: Vector2, _diff?: Vector2, rotate?: number, startAngle?: number, endAngle?: number, clockwise?: boolean);
|
|
496
540
|
isClockwise(): boolean;
|
|
541
|
+
/**
|
|
542
|
+
* A circle/ellipse arc is closed when it sweeps (at least) a full revolution — the sampled
|
|
543
|
+
* outline does not duplicate the start vertex, so the geometric first==last test in the base
|
|
544
|
+
* class would wrongly report a full circle as open and leave a seam gap in the stroke.
|
|
545
|
+
*/
|
|
546
|
+
isClosed(): boolean;
|
|
547
|
+
reverse(): this;
|
|
497
548
|
protected _getDeltaAngle(): number;
|
|
498
549
|
getPoint(t: number, output?: Vector2): Vector2;
|
|
499
550
|
/**
|
|
@@ -541,7 +592,14 @@ declare class CompositeCurve<T extends Curve = Curve> extends Curve {
|
|
|
541
592
|
protected _removeNextPointIfEqualPrevPoint(output: number[], offset: number): number[];
|
|
542
593
|
getSpacedVertices(count?: number, output?: number[]): number[];
|
|
543
594
|
getAdaptiveVertices(output?: number[]): number[];
|
|
595
|
+
/**
|
|
596
|
+
* A composite is closed when its single child is closed (e.g. a lone full-circle arc), or when
|
|
597
|
+
* its assembled outline returns to its start (rectangles, polygons, multi-segment loops).
|
|
598
|
+
*/
|
|
599
|
+
isClosed(): boolean;
|
|
544
600
|
strokeTriangulate(options?: StrokeTriangulateOptions): StrokeTriangulatedResult;
|
|
601
|
+
/** Reverse the sub-curve order and reverse each sub-curve, so the whole outline runs backwards. */
|
|
602
|
+
reverse(): this;
|
|
545
603
|
getFillVertices(options?: FillTriangulateOptions): number[];
|
|
546
604
|
applyTransform(transform: Transform2D | ((point: Vector2) => void)): this;
|
|
547
605
|
getMinMax(min?: Vector2, max?: Vector2): {
|
|
@@ -564,6 +622,7 @@ declare class CubicBezierCurve extends Curve {
|
|
|
564
622
|
getPoint(t: number, output?: Vector2): Vector2;
|
|
565
623
|
getAdaptiveVertices(output?: number[]): number[];
|
|
566
624
|
getControlPointRefs(): Vector2[];
|
|
625
|
+
reverse(): this;
|
|
567
626
|
protected _solveQuadratic(a: number, b: number, c: number): number[];
|
|
568
627
|
getMinMax(min?: Vector2, max?: Vector2): {
|
|
569
628
|
min: Vector2;
|
|
@@ -589,6 +648,7 @@ declare class LineCurve extends Curve {
|
|
|
589
648
|
getTangent(_t: number, output?: Vector2): Vector2;
|
|
590
649
|
getTangentAt(u: number, output?: Vector2): Vector2;
|
|
591
650
|
getControlPointRefs(): Vector2[];
|
|
651
|
+
reverse(): this;
|
|
592
652
|
getAdaptiveVertices(output?: number[]): number[];
|
|
593
653
|
getMinMax(min?: Vector2, max?: Vector2): {
|
|
594
654
|
min: Vector2;
|
|
@@ -621,6 +681,7 @@ declare class QuadraticBezierCurve extends Curve {
|
|
|
621
681
|
constructor(p1?: Vector2, cp?: Vector2, p2?: Vector2);
|
|
622
682
|
getPoint(t: number, output?: Vector2): Vector2;
|
|
623
683
|
getControlPointRefs(): Vector2[];
|
|
684
|
+
reverse(): this;
|
|
624
685
|
getAdaptiveVertices(output?: number[]): number[];
|
|
625
686
|
getMinMax(min?: Vector2, max?: Vector2): {
|
|
626
687
|
min: Vector2;
|
|
@@ -665,6 +726,7 @@ declare class SplineCurve extends Curve {
|
|
|
665
726
|
constructor(points?: Vector2[]);
|
|
666
727
|
getPoint(t: number, output?: Vector2): Vector2;
|
|
667
728
|
getControlPointRefs(): Vector2[];
|
|
729
|
+
reverse(): this;
|
|
668
730
|
copyFrom(source: SplineCurve): this;
|
|
669
731
|
}
|
|
670
732
|
|
|
@@ -676,6 +738,13 @@ declare class CurvePath extends CompositeCurve {
|
|
|
676
738
|
addPoints(points: Vector2[]): this;
|
|
677
739
|
addCommands(commands: Path2DCommand[]): this;
|
|
678
740
|
addData(data: string): this;
|
|
741
|
+
/**
|
|
742
|
+
* A sub-path is closed if it was explicitly closed (`autoClose`, i.e. a `Z`/`closePath`), or if
|
|
743
|
+
* it forms a geometric loop / wraps a single closed primitive (handled by the base class).
|
|
744
|
+
*/
|
|
745
|
+
isClosed(): boolean;
|
|
746
|
+
/** Reverse direction, then refresh the {@link startPoint}/{@link currentPoint} cursors. */
|
|
747
|
+
reverse(): this;
|
|
679
748
|
protected _closeVertices(output: number[]): number[];
|
|
680
749
|
getUnevenVertices(count?: number, output?: number[]): number[];
|
|
681
750
|
getSpacedVertices(count?: number, output?: number[]): number[];
|
|
@@ -760,6 +829,23 @@ declare class Path2D<T = any> extends CompositeCurve<CurvePath> {
|
|
|
760
829
|
/** Per-sub-path sampled rings, cached for repeated hit tests. */
|
|
761
830
|
protected _getRings(): number[][];
|
|
762
831
|
isPointInFill(point: Vector2Like, options?: IsPointInFillOptions): boolean;
|
|
832
|
+
/** Build a `Path2D` from flat rings (`[x0,y0,…]` per sub-path); closed-and-filled as sub-paths. */
|
|
833
|
+
static fromRings(rings: number[][], style?: Partial<Path2DStyle>): Path2D;
|
|
834
|
+
/**
|
|
835
|
+
* Boolean (path) operation against another path, returning a NEW `Path2D` whose outline is the
|
|
836
|
+
* polygonal result. Curves are sampled before clipping, so the result is a polygonal
|
|
837
|
+
* approximation (see {@link polygonBoolean}). The result inherits this path's `style` unless
|
|
838
|
+
* overridden via `style`. Holes are emitted as oppositely-wound sub-paths (nonzero fill).
|
|
839
|
+
*/
|
|
840
|
+
booleanOp(op: BooleanOp, other: Path2D, style?: Partial<Path2DStyle>): Path2D;
|
|
841
|
+
/** `this ∪ other` — the combined filled area. */
|
|
842
|
+
union(other: Path2D, style?: Partial<Path2DStyle>): Path2D;
|
|
843
|
+
/** `this ∩ other` — only the overlapping area. */
|
|
844
|
+
intersection(other: Path2D, style?: Partial<Path2DStyle>): Path2D;
|
|
845
|
+
/** `this − other` — this path with `other` cut away. */
|
|
846
|
+
difference(other: Path2D, style?: Partial<Path2DStyle>): Path2D;
|
|
847
|
+
/** `this ⊕ other` — areas covered by exactly one of the two paths. */
|
|
848
|
+
xor(other: Path2D, style?: Partial<Path2DStyle>): Path2D;
|
|
763
849
|
/**
|
|
764
850
|
* Test whether a point lies on this path's stroke. A hit on any sub-path counts.
|
|
765
851
|
*
|
|
@@ -833,6 +919,40 @@ declare class Path2DSet<T = any> {
|
|
|
833
919
|
}>): HTMLCanvasElement;
|
|
834
920
|
}
|
|
835
921
|
|
|
922
|
+
interface PosTan {
|
|
923
|
+
position: Vector2;
|
|
924
|
+
tangent: Vector2;
|
|
925
|
+
angle: number;
|
|
926
|
+
}
|
|
927
|
+
/**
|
|
928
|
+
* PathKit/Skia-style arc-length measurement over any {@link Curve} (including `CurvePath` and
|
|
929
|
+
* `Path2D`). Wraps the curve's existing arc-length cache, so repeated queries are cheap.
|
|
930
|
+
*
|
|
931
|
+
* ```ts
|
|
932
|
+
* const measure = new PathMeasure(path)
|
|
933
|
+
* const { position, angle } = measure.getPosTan(measure.getLength() * progress)
|
|
934
|
+
* ```
|
|
935
|
+
*/
|
|
936
|
+
declare class PathMeasure {
|
|
937
|
+
curve: Curve;
|
|
938
|
+
constructor(curve: Curve);
|
|
939
|
+
/** Total arc length of the path. */
|
|
940
|
+
getLength(): number;
|
|
941
|
+
/** Whether the path forms a closed loop (see {@link Curve.isClosed}). */
|
|
942
|
+
isClosed(): boolean;
|
|
943
|
+
/** Point + unit tangent + tangent angle at an absolute arc-length `distance` (clamped). */
|
|
944
|
+
getPosTan(distance: number): PosTan;
|
|
945
|
+
/** Point at an absolute arc-length `distance` (clamped to `[0, getLength()]`). */
|
|
946
|
+
getPosition(distance: number): Vector2;
|
|
947
|
+
/** Point + tangent at a normalized progress `t ∈ [0, 1]` along the path. */
|
|
948
|
+
getPosTanAtProgress(t: number): PosTan;
|
|
949
|
+
/**
|
|
950
|
+
* Evenly sample the path into `count + 1` {@link PosTan} entries (arc-length spaced), e.g. to
|
|
951
|
+
* lay glyphs along a path or drive an `animate(progress)`-style traversal.
|
|
952
|
+
*/
|
|
953
|
+
sample(count?: number): PosTan[];
|
|
954
|
+
}
|
|
955
|
+
|
|
836
956
|
declare class FFDControlGrid {
|
|
837
957
|
rows: number;
|
|
838
958
|
cols: number;
|
|
@@ -875,5 +995,5 @@ declare function svgToDom(svg: string | SVGElement): SVGElement;
|
|
|
875
995
|
|
|
876
996
|
declare function svgToPath2DSet(svg: string | SVGElement): Path2DSet;
|
|
877
997
|
|
|
878
|
-
export { ArcCurve, BoundingBox, CompositeCurve, CubicBezierCurve, Curve, CurvePath, EllipseCurve, EquilateralPolygonCurve, FFDControlGrid, LineCurve, PI, PI_2, Path2D, Path2DSet, PolygonCurve, QuadraticBezierCurve, RectangleCurve, RoundRectangleCurve, SplineCurve, Transform2D, Vector2, applyFFD, catmullRom, cubicBezier, drawPoint, fillTriangulate, getAdaptiveCubicBezierCurvePoints, getAdaptiveQuadraticBezierCurvePoints, getDirectedArea, getIntersectionPoint, nonzeroFillRule, parseArcCommand, parseCssArg, parseCssArgs, parseCssFunctions, parsePathDataArgs, pointInPolygon, pointInPolygons, pointToPolylineDistance, pointToSegmentDistance, quadraticBezier, setCanvasContext, strokeTriangulate, svgPathCommandsAddToPath2D, svgPathCommandsToData, svgPathDataToCommands, svgToDom, svgToPath2DSet, toKebabCase };
|
|
879
|
-
export type { CssFunction, CssFunctionArg, DrawPointOptions, FillRule, FillTriangulateOptions, FillTriangulatedResult, IsPointInFillOptions, IsPointInStrokeOptions, LineCap, LineJoin, LineStyle, ParseCssFunctionContext, Path2DCommand, Path2DData, Path2DDrawStyle, Path2DStyle, StrokeLinecap, StrokeLinejoin, StrokeTriangulateOptions, StrokeTriangulatedResult, TransformableObject, TriangulatedResult, Vector2Like };
|
|
998
|
+
export { ArcCurve, BoundingBox, CompositeCurve, CubicBezierCurve, Curve, CurvePath, EllipseCurve, EquilateralPolygonCurve, FFDControlGrid, LineCurve, PI, PI_2, Path2D, Path2DSet, PathMeasure, PolygonCurve, QuadraticBezierCurve, RectangleCurve, RoundRectangleCurve, SplineCurve, Transform2D, Vector2, applyFFD, catmullRom, cubicBezier, drawPoint, fillTriangulate, getAdaptiveCubicBezierCurvePoints, getAdaptiveQuadraticBezierCurvePoints, getDirectedArea, getIntersectionPoint, nonzeroFillRule, parseArcCommand, parseCssArg, parseCssArgs, parseCssFunctions, parsePathDataArgs, pointInPolygon, pointInPolygons, pointToPolylineDistance, pointToSegmentDistance, polygonBoolean, quadraticBezier, resolveLineStyle, setCanvasContext, strokeTriangulate, svgPathCommandsAddToPath2D, svgPathCommandsToData, svgPathDataToCommands, svgToDom, svgToPath2DSet, toKebabCase };
|
|
999
|
+
export type { BooleanOp, CssFunction, CssFunctionArg, DrawPointOptions, FillRule, FillTriangulateOptions, FillTriangulatedResult, FlatRing, IsPointInFillOptions, IsPointInStrokeOptions, LineCap, LineJoin, LineStyle, ParseCssFunctionContext, Path2DCommand, Path2DData, Path2DDrawStyle, Path2DStyle, PosTan, StrokeLinecap, StrokeLinejoin, StrokeTriangulateOptions, StrokeTriangulatedResult, TransformableObject, TriangulatedResult, Vector2Like };
|