path2d
Version:
Path2D API for node. Can be used for server-side rendering with canvas
540 lines (534 loc) • 22.8 kB
text/typescript
/**
* SVG path commands and custom canvas commands.
*
* Standard SVG path commands:
* - M/m: Move to (absolute/relative)
* - L/l: Line to (absolute/relative)
* - H/h: Horizontal line to (absolute/relative)
* - V/v: Vertical line to (absolute/relative)
* - A/a: Arc (absolute/relative)
* - C/c: Cubic Bézier curve (absolute/relative)
* - S/s: Smooth cubic Bézier curve (absolute/relative)
* - Q/q: Quadratic Bézier curve (absolute/relative)
* - T/t: Smooth quadratic Bézier curve (absolute/relative)
* - Z/z: Close path
*
* Custom canvas commands:
* - AC: Arc (canvas arc method)
* - AT: Arc to (canvas arcTo method)
* - E: Ellipse (canvas ellipse method)
* - R: Rectangle (canvas rect method)
* - RR: Rounded rectangle (canvas roundRect method)
*/
type Command = "M" | "m" | "L" | "l" | "H" | "h" | "V" | "v" | "A" | "a" | "C" | "c" | "S" | "s" | "Q" | "q" | "T" | "t" | "Z" | "z" | "AC" | "AT" | "E" | "R" | "RR";
/** Move command: [command, x, y] */
type MovePathCommand = ["m" | "M", number, number];
/** Line command: [command, x, y] */
type LinePathCommand = ["l" | "L", number, number];
/** Horizontal line command: [command, x] */
type HorizontalPathCommand = ["h" | "H", number];
/** Vertical line command: [command, y] */
type VerticalPathCommand = ["v" | "V", number];
/** Arc command: [command, rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y] */
type ArcPathCommand = ["a" | "A", number, number, number, boolean, boolean, number, number];
/** Cubic Bézier curve command: [command, x1, y1, x2, y2, x, y] */
type CurvePathCommand = ["c" | "C", number, number, number, number, number, number];
/** Smooth cubic Bézier curve command: [command, x2, y2, x, y] */
type ShortCurvePathCommand = ["s" | "S", number, number, number, number];
/** Quadratic Bézier curve command: [command, x1, y1, x, y] */
type QuadraticCurvePathCommand = ["q" | "Q", number, number, number, number];
/** Smooth quadratic Bézier curve command: [command, x, y] */
type ShortQuadraticCurvePathCommand = ["t" | "T", number, number];
/** Close path command: [command] */
type ClosePathCommand = ["z" | "Z"];
/** Canvas arc command: [command, x, y, radius, startAngle, endAngle, counterclockwise] */
type ArcCommand = ["AC", number, number, number, number, number, boolean];
/** Canvas arcTo command: [command, x1, y1, x2, y2, radius] */
type ArcToCommand = ["AT", number, number, number, number, number];
/** Canvas ellipse command: [command, x, y, radiusX, radiusY, rotation, startAngle, endAngle, counterclockwise] */
type EllipseCommand = ["E", number, number, number, number, number, number, number, boolean];
/** Canvas rectangle command: [command, x, y, width, height] */
type RectCommand = ["R", number, number, number, number];
/** Canvas rounded rectangle command: [command, x, y, width, height, radii] */
type RoundRectCommand = [
"RR",
number,
number,
number,
number,
number | DOMPointInit | (number | DOMPointInit)[]
];
/** Generic command for any path operation */
type GenericCommand = [Command, ...(number | boolean | number[])[]];
/** Canvas fill rule for determining how to fill paths */
type CanvasFillRule = "nonzero" | "evenodd";
/**
* Union type representing all possible path commands.
* This includes both SVG path commands and custom canvas commands.
*/
type PathCommand = MovePathCommand | LinePathCommand | HorizontalPathCommand | VerticalPathCommand | ArcPathCommand | CurvePathCommand | ShortCurvePathCommand | QuadraticCurvePathCommand | ShortQuadraticCurvePathCommand | ClosePathCommand | ArcCommand | ArcToCommand | EllipseCommand | RectCommand | RoundRectCommand | GenericCommand;
/**
* Represents a point in 2D or 3D space.
* Used for specifying rounded rectangle corner radii and other geometric operations.
*/
type DOMPointInit = {
/** The w (perspective) coordinate */
w?: number;
/** The x coordinate */
x?: number;
/** The y coordinate */
y?: number;
/** The z coordinate */
z?: number;
};
/**
* Interface representing the CanvasRenderingContext2D API methods used by Path2D.
* This interface includes both standard canvas methods and Path2D-enhanced methods.
*/
interface ICanvasRenderingContext2D {
/** Starts a new path by emptying the list of sub-paths */
beginPath: () => void;
/** Saves the current drawing state */
save: () => void;
/** Adds a translation transformation to the current matrix */
translate: (x: number, y: number) => void;
/** Adds a rotation transformation to the current matrix */
rotate: (angle: number) => void;
/** Adds a scaling transformation to the current matrix */
scale: (x: number, y: number) => void;
/** Restores the most recently saved drawing state */
restore: () => void;
/** Moves the starting point of a new sub-path to the specified coordinates */
moveTo: (x: number, y: number) => void;
/** Connects the last point in the current sub-path to the specified coordinates with a straight line */
lineTo: (x: number, y: number) => void;
/** Adds a circular arc to the current path */
arc: (x: number, y: number, r: number, start: number, end: number, ccw: boolean) => void;
/** Adds an arc to the current path with the given control points and radius */
arcTo: (x1: number, y1: number, x2: number, y2: number, r: number) => void;
/** Adds an elliptical arc to the current path */
ellipse: (x: number, y: number, rx: number, ry: number, angle: number, start: number, end: number, ccw: boolean) => void;
/** Closes the current sub-path by connecting the last point to the first point with a straight line */
closePath: () => void;
/** Adds a cubic Bézier curve to the current path */
bezierCurveTo: (cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number) => void;
/** Adds a quadratic Bézier curve to the current path */
quadraticCurveTo: (cpx: number, cpy: number, x: number, y: number) => void;
/** Adds a rectangle to the current path */
rect: (x: number, y: number, width: number, height: number) => void;
/** Determines if a point is inside the current path or a specified Path2D object */
isPointInPath: {
(x: number, y: number, fillRule?: CanvasFillRule): boolean;
(path: Path2D, x: number, y: number, fillRule?: CanvasFillRule): boolean;
};
/** Creates a clipping region from the current path or a specified Path2D object */
clip: {
(fillRule?: CanvasFillRule): void;
(path: Path2D, fillRule?: CanvasFillRule): void;
};
/** Fills the current path or a specified Path2D object */
fill: {
(fillRule?: CanvasFillRule): void;
(path: Path2D, fillRule?: CanvasFillRule): void;
};
/** Strokes the current path or a specified Path2D object */
stroke: (path?: Path2D) => void;
/** Adds a rounded rectangle to the current path */
roundRect: (x: number, y: number, width: number, height: number, radii?: number | DOMPointInit | (number | DOMPointInit)[]) => void;
}
/**
* Utility type representing a constructor function with a prototype.
* Used for typing constructor objects that can be modified with polyfills.
*/
type Prototype<T> = {
prototype: T;
new (): T;
};
/**
* Utility type that makes specific properties of T optional.
* Used for creating flexible interfaces where some methods might not be available.
*
* @template T - The base type
* @template K - The keys to make optional
*/
type MakeOptional<T, K extends keyof T> = Omit<T, K> & {
[P in K]?: T[P];
};
/**
* Implements the browser's Path2D API for creating and manipulating 2D paths.
* This class provides methods for building complex paths using lines, curves, arcs, and shapes.
*
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Path2D} MDN Path2D Documentation
*
* @example
* ```typescript
* // Create a new path
* const path = new Path2D();
* path.moveTo(10, 10);
* path.lineTo(100, 100);
* path.arc(50, 50, 20, 0, Math.PI * 2);
*
* // Create from SVG path string
* const svgPath = new Path2D("M10,10 L100,100 Z");
*
* // Copy existing path
* const copiedPath = new Path2D(path);
* ```
*/
declare class Path2D {
#private;
/**
* Creates a new Path2D object.
*
* @param path - Optional path to initialize from. Can be another Path2D object or an SVG path string
*
* @example
* ```typescript
* // Empty path
* const path1 = new Path2D();
*
* // From SVG path string
* const path2 = new Path2D("M10,10 L100,100 Z");
*
* // Copy from another Path2D
* const path3 = new Path2D(path1);
* ```
*/
constructor(path?: Path2D | string);
/**
* Adds a custom command to the path's command list.
* This is primarily used internally for extending functionality.
*
* @param command - The path command to add
*/
addCustomCommand(command: PathCommand): void;
/**
* Adds the commands from another Path2D object to this path.
*
* @param path - The Path2D object whose commands should be added to this path
*
* @example
* ```typescript
* const path1 = new Path2D("M10,10 L20,20");
* const path2 = new Path2D("L30,30 Z");
* path1.addPath(path2); // path1 now contains both sets of commands
* ```
*/
addPath(path: Path2D): void;
/**
* Moves the starting point of a new sub-path to the specified coordinates.
*
* @param x - The x-coordinate of the new starting point
* @param y - The y-coordinate of the new starting point
*
* @example
* ```typescript
* const path = new Path2D();
* path.moveTo(10, 10);
* ```
*/
moveTo(x: number, y: number): void;
/**
* Connects the last point in the current sub-path to the specified coordinates with a straight line.
*
* @param x - The x-coordinate of the end point
* @param y - The y-coordinate of the end point
*
* @example
* ```typescript
* const path = new Path2D();
* path.moveTo(10, 10);
* path.lineTo(100, 100);
* ```
*/
lineTo(x: number, y: number): void;
/**
* Adds a circular arc to the current path.
*
* @param x - The x-coordinate of the arc's center
* @param y - The y-coordinate of the arc's center
* @param radius - The arc's radius
* @param startAngle - The starting angle in radians
* @param endAngle - The ending angle in radians
* @param counterclockwise - Whether the arc should be drawn counterclockwise (default: false)
*
* @example
* ```typescript
* const path = new Path2D();
* path.arc(50, 50, 25, 0, Math.PI * 2); // Full circle
* path.arc(100, 100, 30, 0, Math.PI, true); // Half circle, counterclockwise
* ```
*/
arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, counterclockwise?: boolean): void;
/**
* Adds an arc to the current path with the given control points and radius.
*
* @param x1 - The x-coordinate of the first control point
* @param y1 - The y-coordinate of the first control point
* @param x2 - The x-coordinate of the second control point
* @param y2 - The y-coordinate of the second control point
* @param r - The arc's radius
*
* @example
* ```typescript
* const path = new Path2D();
* path.moveTo(20, 20);
* path.arcTo(100, 20, 100, 100, 50);
* ```
*/
arcTo(x1: number, y1: number, x2: number, y2: number, r: number): void;
/**
* Adds an elliptical arc to the current path.
*
* @param x - The x-coordinate of the ellipse's center
* @param y - The y-coordinate of the ellipse's center
* @param radiusX - The ellipse's major-axis radius
* @param radiusY - The ellipse's minor-axis radius
* @param rotation - The rotation angle of the ellipse in radians
* @param startAngle - The starting angle in radians
* @param endAngle - The ending angle in radians
* @param counterclockwise - Whether the arc should be drawn counterclockwise (default: false)
*
* @example
* ```typescript
* const path = new Path2D();
* path.ellipse(50, 50, 30, 20, Math.PI / 4, 0, Math.PI * 2);
* ```
*/
ellipse(x: number, y: number, radiusX: number, radiusY: number, rotation: number, startAngle: number, endAngle: number, counterclockwise?: boolean): void;
/**
* Closes the current sub-path by connecting the last point to the first point with a straight line.
*
* @example
* ```typescript
* const path = new Path2D();
* path.moveTo(10, 10);
* path.lineTo(100, 10);
* path.lineTo(100, 100);
* path.closePath(); // Creates a triangle
* ```
*/
closePath(): void;
/**
* Adds a cubic Bézier curve to the current path.
*
* @param cp1x - The x-coordinate of the first control point
* @param cp1y - The y-coordinate of the first control point
* @param cp2x - The x-coordinate of the second control point
* @param cp2y - The y-coordinate of the second control point
* @param x - The x-coordinate of the end point
* @param y - The y-coordinate of the end point
*
* @example
* ```typescript
* const path = new Path2D();
* path.moveTo(20, 20);
* path.bezierCurveTo(20, 100, 200, 100, 200, 20);
* ```
*/
bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): void;
/**
* Adds a quadratic Bézier curve to the current path.
*
* @param cpx - The x-coordinate of the control point
* @param cpy - The y-coordinate of the control point
* @param x - The x-coordinate of the end point
* @param y - The y-coordinate of the end point
*
* @example
* ```typescript
* const path = new Path2D();
* path.moveTo(20, 20);
* path.quadraticCurveTo(100, 100, 200, 20);
* ```
*/
quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void;
/**
* Adds a rectangle to the current path.
*
* @param x - The x-coordinate of the rectangle's top-left corner
* @param y - The y-coordinate of the rectangle's top-left corner
* @param width - The rectangle's width
* @param height - The rectangle's height
*
* @example
* ```typescript
* const path = new Path2D();
* path.rect(10, 10, 100, 50);
* ```
*/
rect(x: number, y: number, width: number, height: number): void;
/**
* Adds a rounded rectangle to the current path.
*
* @param x - The x-coordinate of the rectangle's top-left corner
* @param y - The y-coordinate of the rectangle's top-left corner
* @param w - The rectangle's width
* @param h - The rectangle's height
* @param radii - The corner radii. Can be a number, DOMPointInit, or array of up to 4 values
*
* @example
* ```typescript
* const path = new Path2D();
* path.roundRect(10, 10, 100, 50, 10); // All corners with radius 10
* path.roundRect(10, 70, 100, 50, [10, 20]); // Different horizontal/vertical radii
* path.roundRect(10, 130, 100, 50, [5, 10, 15, 20]); // Each corner different
* ```
*/
roundRect(x: number, y: number, w: number, h: number, radii?: number | DOMPointInit | (number | DOMPointInit)[]): void;
}
/**
* Enhances CanvasRenderingContext2D with Path2D support for stroke, fill, clip, and isPointInPath methods.
*
* This function modifies the prototype of CanvasRenderingContext2D to accept Path2D objects
* as parameters in addition to the standard path operations. It preserves the original
* functionality while adding Path2D compatibility.
*
* Modified methods:
* - `fill()`: Can now accept a Path2D object as first parameter
* - `stroke()`: Can now accept a Path2D object as parameter
* - `clip()`: Can now accept a Path2D object as first parameter
* - `isPointInPath()`: Can now accept a Path2D object as first parameter
*
* @param CanvasRenderingContext2D - The CanvasRenderingContext2D constructor object to enhance
*
* @example
* ```typescript
* // Apply Path2D support to canvas context
* applyPath2DToCanvasRenderingContext(CanvasRenderingContext2D);
*
* // Now you can use Path2D objects with canvas methods
* const canvas = document.createElement('canvas');
* const ctx = canvas.getContext('2d');
* const path = new Path2D('M10,10 L50,50 Z');
*
* ctx.fill(path); // Fill the Path2D object
* ctx.stroke(path); // Stroke the Path2D object
* ctx.clip(path); // Use Path2D object as clipping region
* const isInside = ctx.isPointInPath(path, 25, 25); // Test point against Path2D
* ```
*/
declare function applyPath2DToCanvasRenderingContext(CanvasRenderingContext2D?: Prototype<ICanvasRenderingContext2D>): void;
/**
* Polyfills the roundRect method on CanvasRenderingContext2D for browsers that don't support it natively.
*
* The roundRect method adds a rounded rectangle to the current path. This polyfill ensures
* compatibility with browsers like Firefox that may not have native roundRect support.
*
* @param CanvasRenderingContext2D - The CanvasRenderingContext2D constructor object to polyfill
*
* @example
* ```typescript
* // Apply roundRect polyfill
* applyRoundRectToCanvasRenderingContext2D(CanvasRenderingContext2D);
*
* // Now roundRect is available even in unsupported browsers
* const canvas = document.createElement('canvas');
* const ctx = canvas.getContext('2d');
* ctx.roundRect(10, 10, 100, 50, 10); // Works in all browsers
* ```
*
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/roundRect} MDN roundRect Documentation
*/
declare function applyRoundRectToCanvasRenderingContext2D(CanvasRenderingContext2D?: Prototype<MakeOptional<ICanvasRenderingContext2D, "roundRect">>): void;
/**
* Polyfills the roundRect method on Path2D for browsers that don't support it natively.
*
* The roundRect method adds a rounded rectangle to a Path2D object. This polyfill ensures
* compatibility with browsers that may not have native roundRect support on Path2D objects.
*
* @param P2D - The Path2D constructor object to polyfill
*
* @example
* ```typescript
* // Apply roundRect polyfill to Path2D
* applyRoundRectToPath2D(Path2D);
*
* // Now roundRect is available on Path2D objects
* const path = new Path2D();
* path.roundRect(10, 10, 100, 50, [10, 20]); // Works in all browsers
* ```
*
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Path2D} MDN Path2D Documentation
*/
declare function applyRoundRectToPath2D(P2D?: Prototype<MakeOptional<Path2D, "roundRect">>): void;
/**
* Parses an SVG path data string into an array of path commands.
*
* Each command is represented as an array where the first element is the command letter
* and subsequent elements are the numeric arguments for that command.
*
* Supports all standard SVG path commands:
*
* @param path - The SVG path data string to parse
* @returns Array of path commands, each as [command, ...args]
*
* @see {@link https://www.w3.org/TR/SVG/paths.html#PathDataGeneralInformation} SVG Path Specification
*
* @example
* ```typescript
* // Simple path with move and line commands
* parsePath("M10,10 L20,20 Z")
* // Returns: [["M", 10, 10], ["L", 20, 20], ["Z"]]
*
* // Complex path with curves and arcs
* parsePath("M10,10 C20,20 30,30 40,40 A5,5 0 0,1 50,50")
* // Returns: [["M", 10, 10], ["C", 20, 20, 30, 30, 40, 40], ["A", 5, 5, 0, false, true, 50, 50]]
*
* // Relative commands
* parsePath("m10,10 l10,0 l0,10 z")
* // Returns: [["m", 10, 10], ["l", 10, 0], ["l", 0, 10], ["z"]]
* ```
*/
declare function parsePath(path: string): PathCommand[];
/**
* Adds a rounded rectangle to the current path or canvas context.
*
* This function implements the roundRect method that can be used on both Path2D objects
* and CanvasRenderingContext2D contexts. It supports flexible radius specifications
* including uniform radii, separate horizontal/vertical radii, and individual corner radii.
*
* Radius specification:
* - Single number: Same radius for all corners
* - Single DOMPointInit: x for horizontal radius, y for vertical radius (all corners)
* - Array with 1 element: Same as single value
* - Array with 2 elements: [horizontal, vertical] radii for all corners
* - Array with 3 elements: [top-left, top-right/bottom-left, bottom-right]
* - Array with 4 elements: [top-left, top-right, bottom-right, bottom-left]
*
* @param this - The Path2D or CanvasRenderingContext2D object to draw on
* @param x - The x-coordinate of the rectangle's top-left corner
* @param y - The y-coordinate of the rectangle's top-left corner
* @param width - The width of the rectangle
* @param height - The height of the rectangle
* @param radii - The corner radii specification (default: 0)
*
* @throws {RangeError} When an invalid number of radii are provided (must be 1-4)
* @throws {RangeError} When any radius value is negative
* @throws {TypeError} When a radius value is not a number or DOMPointInit
*
* @example
* ```typescript
* // On a canvas context
* const canvas = document.createElement('canvas');
* const ctx = canvas.getContext('2d');
*
* // Simple rounded rectangle with uniform radius
* ctx.roundRect(10, 10, 100, 50, 10);
*
* // Different horizontal and vertical radii
* ctx.roundRect(10, 70, 100, 50, { x: 20, y: 10 });
*
* // Individual corner radii
* ctx.roundRect(10, 130, 100, 50, [5, 10, 15, 20]);
*
* // On a Path2D object
* const path = new Path2D();
* path.roundRect(10, 10, 100, 50, [10, 20]);
* ctx.fill(path);
* ```
*
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/roundRect} MDN roundRect Documentation
*/
declare function roundRect(this: Path2D | ICanvasRenderingContext2D, x: number, y: number, width: number, height: number, radii?: number | DOMPointInit | (number | DOMPointInit)[]): void;
export { type ArcCommand, type ArcPathCommand, type ArcToCommand, type CanvasFillRule, type ClosePathCommand, type Command, type CurvePathCommand, type DOMPointInit, type EllipseCommand, type GenericCommand, type HorizontalPathCommand, type ICanvasRenderingContext2D, type LinePathCommand, type MakeOptional, type MovePathCommand, Path2D, type PathCommand, type Prototype, type QuadraticCurvePathCommand, type RectCommand, type RoundRectCommand, type ShortCurvePathCommand, type ShortQuadraticCurvePathCommand, type VerticalPathCommand, applyPath2DToCanvasRenderingContext, applyRoundRectToCanvasRenderingContext2D, applyRoundRectToPath2D, parsePath, roundRect };