warpvas
Version:
This JavaScript library enables fast and efficient image distortion transformations using Canvas 2D.
1,243 lines • 58.5 kB
TypeScript
import { Bezier } from 'bezier-js';
/**
* Vertex position enum for warp region
*
* Used to identify the four vertex coordinates of the warp region.
*
* @enum {string}
*/
export declare enum VertexPosition {
/** Top left vertex */
TOP_LEFT = "tl",
/** Top right vertex */
TOP_RIGHT = "tr",
/** Bottom left vertex */
BOTTOM_LEFT = "bl",
/** Bottom right vertex */
BOTTOM_RIGHT = "br"
}
/**
* Warp region boundary direction enum
*
* Used to identify the four boundary directions of the warp region.
*
* @enum {string}
*/
export declare enum Direction {
TOP = "top",
BOTTOM = "bottom",
LEFT = "left",
RIGHT = "right"
}
/**
* Warp region type
*
* An object type that describes a rectangular warp region, containing coordinate information of the four vertices.
*
* @example
* const region: Region = {
* tl: { x: 0, y: 0 }, // Top-left coordinates
* tr: { x: 100, y: 0 }, // Top-right coordinates
* bl: { x: 0, y: 100 }, // Bottom-left coordinates
* br: { x: 100, y: 100 } // Bottom-right coordinates
* };
*/
export type Region = Record<VertexPosition, Coord>;
/**
* Split point calculation strategy interface type
*
* Defines the strategy name and calculation method for grid split points,
* which determines how to generate grid split points inside the warp region,
* affecting the final warp effect.
*
* @property {string} name - Custom identifier name of the strategy
* @property {Function} execute - Method to calculate split points under the warp strategy
* @property {Warpvas} execute.warpvas - Current warpvas instance object
* @property {Coord[][][]} execute.return - Returns a 3D array representing the grid point coordinates of each split region
* [region row][region column][grid point coordinates]
*/
export type Strategy = {
name: string;
execute: (warpvas: Warpvas) => Coord[][][];
};
/**
* Warpvas rendering configuration options
*
* Controls the rendering effects and debug view display of the warpvas.
* By configuring these options, you can customize the appearance and performance of the warpvas.
*
* @example
* const warpvas = new Warpvas(canvas);
* warpvas.setRenderingConfig({
* padding: 10, // Set 10px padding
* enableAntialias: true, // Enable anti-aliasing
* enableSafeRendering: true, // Enable safe rendering mode
* enableContentDisplay: true, // Display the warped content
* enableGridDisplay: true, // Display the warp grid
* enableGridVertexDisplay: false, // Display grid vertices
* gridColor: { r: 0, g: 255, b: 0, a: 1 } // Use coral red grid
* });
*/
export interface RenderingConfig {
/**
* Padding around the warpvas (in pixels)
*
* Often used to provide some padding area to preserve overflowed warp content
* @default 0
*/
padding: number;
/**
* Whether to enable anti-aliasing
*
* When enabled, it makes image edges smoother, but may slightly affect performance.
* The effect varies across different rendering modes.
* @default true
*/
enableAntialias: boolean;
/**
* Whether to enable safe rendering mode
*
* When enabled, it will automatically fallback to Canvas 2D rendering if WebGL rendering fails,
* preventing the warpvas from not being displayed due to errors.
* @default true
* @remarks Since WebGL rendering is used by default, it's recommended to keep this enabled in production.
*/
enableSafeRendering: boolean;
/**
* Whether to display the warped content
*
* @default true
*/
enableContentDisplay: boolean;
/**
* Whether to display the warp grid
*
* Used for debugging warp effects, visually showing the triangulated mesh of warp divisions
* @default false
*/
enableGridDisplay: boolean;
/**
* Whether to display grid vertices
*
* Used for debugging the positions of grid vertices
* @default false
*/
enableGridVertexDisplay: boolean;
/**
* Grid and grid vertex color configuration
* @property {number} r - Red channel value (0-255)
* @property {number} g - Green channel value (0-255)
* @property {number} b - Blue channel value (0-255)
* @property {number} a - Transparency (0-1)
* @default { r: 255, g: 0, b: 0, a: 1 } // Default red
* @remarks In WebGL rendering mode, changes in transparency may affect the rendering result.
*/
gridColor: {
r: number;
g: number;
b: number;
a: number;
};
}
/**
* Warp deformation state data structure
*
* Contains core data required to describe the deformation state of a texture,
* including split points and mesh deformation data.
*/
export type WarpState = {
/**
* List of relative positions of split points
*/
splitPoints: Coord[];
/**
* Region boundary deformation data
*
* A 3D array storing the Bezier curve control points for the four edges of each split region:
* - First dimension: Region row index
* - Second dimension: Region column index
* - Third dimension: Control points array for the four edges (top/right/bottom/left) of the region
*
* @example
* // Example of boundary data for a 2x2 grid
* regionBounds: [
* [
* { // Top-left region
* top: [{x: 0, y: 0}, ...], // Control points for top edge
* right: [{x: 0, y: 0}, ...], // Control points for right edge
* bottom: [{x: 0, y: 0}, ...], // Control points for bottom edge
* left: [{x: 0, y: 0}, ...] // Control points for left edge
* },
* // ... Top-right region
* ],
* // ... Next row of regions
* ]
*/
regionBounds: Record<Direction, Coord[]>[][];
};
/**
* Warp deformation class
*
* The warp deformation class can create corresponding deformation tool instances based on image sources,
* and can apply deformation to images through internal methods to produce deformed graphic canvases.
*
* @example
* const canvas = document.createElement('canvas');
* const ctx = canvas.getContext('2d');
* if (!ctx) return;
* // Draw a rectangle
* ctx.fillRect(0, 0, canvas.width, canvas.height);
*
* // Create a Warpvas instance, passing the canvas as the image source
* const warpvas = new Warpvas(canvas);
*
* // Drag the top-left corner of the original canvas image to position (50, 50)
* warpvas.updateVertexCoord(0, 0, 'tl', { x: 50, y: 50 });
*
* // Generate the deformed canvas and add it to the document
* const warpvasCanvas = warpvas.render();
* document.body.appendChild(warpvasCanvas);
*/
export declare class Warpvas {
/**
* Source canvas object
*
* Stores the canvas containing the original image data. If an HTMLImageElement instance is passed to the constructor,
* a new canvas will be automatically created and the image will be drawn onto it to avoid modifying the original image.
*/
source: HTMLCanvasElement;
/**
* List of relative positions of split points
*
* Stores the relative coordinates (range 0-1) of canvas split points. These points divide the canvas into multiple deformable regions,
* where each split point's coordinates are proportional values relative to the canvas dimensions, not actual pixel values.
*
* @remarks To add split points, do not directly manipulate this list. Instead, use the splitRegionByPoint method to add split points.
*
* @see splitRegionByPoint Learn how to add split points to achieve region segmentation
*/
splitPoints: Coord[];
/**
* Pre-deformation regions
*
* 2D array storing the four vertex coordinates of each rectangular region before deformation.
*
* @remarks Array structure: [region row][region column], each region contains four vertices:
* top-left (tl), top-right (tr), bottom-left (bl), bottom-right (br)
*
* @example
* // Access top-left coordinate of the first region
* const topLeft = warpvas.originalRegions[0][0].tl;
*/
originalRegions: Region[][];
/**
* Original grid points
*
* 3D array storing the coordinates of grid points within each region before deformation.
* These coordinates are in their original state and used as mapping data for subsequent deformation calculations.
*
* @remarks Array structure: [region row][region column][list of grid points]
*/
originalRegionPoints: Coord[][][];
/**
* Region boundary curves
*
* Stores the Bezier curve objects for the four edges of each region.
*/
regionBoundaryCurves: Record<Direction, Bezier>[][];
/**
* Deformed grid curves
*
* Stores the grid lines of each region after deformation, including both vertical and horizontal Bezier curves.
* These curves determine the final deformation effect of the image.
*
* @remarks To perform deformation, do not directly manipulate this list.
* Instead, use the updateRegionBoundCoords method to adjust specific curves for boundary deformation effects.
*
* @see updateRegionBoundCoords Learn how to adjust region boundary curves to achieve deformation effects
*/
regionCurves: {
vertical: Bezier[];
horizontal: Bezier[];
}[][];
/**
* Deformed grid points
*
* Stores the coordinates of grid points after deformation. The positions of these points are calculated by the split strategy,
* and different strategies will produce different deformation effects.
*
* @remarks To perform deformation, do not directly manipulate this list.
* Instead, use the updateVertexCoord/updateRegionBoundCoords methods to achieve deformation effects.
*
* @see Strategy Learn more about split strategies
* @see updateVertexCoord Learn how to adjust region vertex coordinates for deformation
* @see updateRegionBoundCoords Learn how to adjust region boundary curves for deformation
*/
regionPoints: Coord[][][];
/**
* Grid split ratio
*
* Controls the density of the grid split, with a value range of 0-1. The smaller the value,
* the denser the grid, resulting in finer deformation effects, but also increasing computation.
* For example, when the value is 0.1, the maximum size of each grid is 10% of the image width.
*
* @default 0.05 Default value, meaning the maximum size of each grid is 5% of the image width.
*
* @see setSplitUnit Learn how to control the grid split ratio
*/
splitUnit: number;
/**
* Split point calculation strategy
*
* Defines how to calculate the grid point positions inside the deformation region.
* The built-in warp strategy is used by default, and you can also set a custom strategy through the setSplitStrategy method.
*
* @see setSplitStrategy Learn how to configure the split calculation strategy
*/
splitStrategy: Strategy;
/**
* Rendering engine type
*
* Specifies the rendering method to use, supports '2d' or 'webgl'.
* WebGL mode has better performance, and when safe rendering configuration is set,
* it will automatically fallback to Canvas in environments where WebGL is not supported.
*
* @default 'webgl'
*
* @see setRenderingContext Learn how to switch rendering engines
*/
renderingContext: '2d' | 'webgl';
/**
* Rendering options
* Controls various parameters of the rendering process, including padding, anti-aliasing, debug grid display, etc.
* These options can be dynamically modified through the setRenderingConfig method.
*
* @see RenderingConfig View all available rendering options
* @see setRenderingConfig Learn how to configure rendering options
*/
renderingConfig: RenderingConfig;
/**
* Safe rendering mode activation flag
*
* Indicates whether safe rendering mode is activated. When the first WebGL
* rendering failure occurs with safe mode configured, this flag enables
* subsequent renders to automatically downgrade to Canvas 2D rendering.
*/
private _safeModeEnabled;
/**
* Image source dimensions cache
*
* Stores the current image source's dimension information,
* triggers grid points recalculation when dimensions change.
*
* @private
*/
private _cacheSourceSize;
/**
* Source image data cache
*
* Stores the original image's pixel data to optimize performance during Web Worker rendering.
* When using Web Workers for rendering, avoiding repeated image data retrieval can significantly improve performance.
*
* @private
*/
private _cacheSourceImageData;
/**
* Input canvas cache
*
* Stores the temporary canvas used for resizing input images.
* Maintaining a separate cache canvas preserves the original image source and ensures data integrity.
*
* @private
*/
private _cacheInputCanvas;
/**
* Output canvas cache
*
* Stores the singleton canvas instance for rendering results.
* Reusing the same canvas across multiple rendering operations reduces memory usage.
*
* @private
* @see setRenderingCanvas Learn how to configure the output canvas in singleton mode
*/
private _cacheOutputCanvas;
/**
* Input size constraints
*
* Defines maximum dimensions allowed for input canvas.
* Canvas exceeding these constraints will be proportionally scaled down to fit.
*
* @private
* @see setInputLimitSize Learn how setting input size limits utilizes this cache
*/
private _inputLimitSize;
/**
* Input scaling ratio
*
* Records the actual scaling factor caused by input size constraints.
* When input images require resizing, this value captures the applied scaling ratio.
*
* @private
* @default 1
*/
private _inputLimitScale;
/**
* Output size constraints
*
* Defines maximum dimensions allowed for output canvas.
* Deformed results exceeding these constraints will be automatically scaled down proportionally to fit.
*
* @private
* @see setOutputLimitSize Learn how to configure output size constraints
* @remarks Proper configuration prevents performance issues and rendering failures caused by oversized canvases.
*/
private _outputLimitSize;
/**
* Output scaling ratio
*
* Records the actual scaling factor resulting from output size constraints.
* Captures the applied ratio when output canvas requires resizing.
*
* @private
* @default 1
*/
private _outputLimitScale;
/**
* Warpvas constructor
*
* Creates a new warp deformation canvas instance. Accepts an image or canvas as source,
* with optional initial grid division settings.
*
* @param source - Image source (HTMLImageElement or HTMLCanvasElement)
* - For images: auto-creates canvas and draws image
* - For canvases: uses directly as source
*
* @param rows - Initial horizontal divisions
* - Must be integer ≥ 1
* - 1 = no horizontal division
* - 2 = adds midline horizontal division
* - Default: 1
*
* @param columns - Initial vertical divisions
* - Must be integer ≥ 1
* - 1 = no vertical division
* - 2 = adds midline vertical division
* - Default: 1
*
* @example
* // Create with image
* const img = new Image();
* img.src = 'example.jpg';
* img.onload = () => new Warpvas(img);
*
* // Create with canvas and 2x2 grid
* const canvas = document.createElement('canvas');
* new Warpvas(canvas, 2, 2);
*/
constructor(source: HTMLCanvasElement | HTMLImageElement, rows?: number, columns?: number);
/**
* Maximum split unit in pixels
*
* Calculates the maximum grid division size allowed for current texture in pixels.
* This value is determined by splitUnit (division ratio) and image width.
*
* @returns {number} Maximum split unit in pixels
* - When splitUnit is 0.1: returns 10% of image width
* - When splitUnit is 0.05: returns 5% of image width
*
* @example
* // Assuming image width is 1000px with splitUnit 0.1
* const maxSize = warpvas.maxSplitUnitPixel; // Returns 100px
*
* @see splitUnit See split ratio configuration
*/
get maxSplitUnitPixel(): number;
/**
* Actual scaling ratio of the canvas
*
* Returns the scaling ratio relative to original dimensions.
* The ratio combines both input and output limitations:
* - Input limitations: Automatic scaling when processing large images
* - Output limitations: Prevents oversized canvas generation
*
* @returns {{ x: number, y: number }} Scaling ratios in x/y dimensions
* - 1 = original size
* - <1 = downscaled
* - x/y always equal to prevent distortion
*
* @example
* const { x, y } = warpvas.scale;
* console.log(`Canvas scaled to ${x * 100}% of original size`);
*/
get scale(): {
x: number;
y: number;
};
/**
* Built-in default warp splitting strategy
*
* Default grid splitting strategy that generates grid points by calculating
* midpoints between intersections of horizontal/vertical Bezier curves.
* This strategy effectively demonstrates planar warp effects, particularly
* suitable for:
* - Image bending deformation
* - Perspective transformation
* - Wave effect simulations
*
* @param warpvas - Current warp canvas instance
* @returns 3D array containing grid coordinates of all split regions
* - 1st dimension: Region row index
* - 2nd dimension: Region column index
* - 3rd dimension: List of grid points in the region
*
* @example
* // Default strategy is already applied, but can be explicitly set:
* warpvas.setSplitStrategy({
* name: 'default',
* execute: Warpvas.strategy
* });
*
* @remarks
* Strategy workflow:
* 1. Iterate through each split region
* 2. Calculate intersections of horizontal/vertical Bezier curves within region
* 3. Use midpoints of intersecting pairs as grid points
* 4. Ensures uniform grid distribution that follows curve deformations
*/
static strategy(warpvas: Warpvas): Coord[][][];
/**
* Serialize warp state data
*
* Compresses warp deformation data into base64 string format for transmission/storage.
* The compressed data includes:
* - Split points configuration
* - Region boundary deformations
*
* @param warpState - Warp state object containing:
* - splitPoints: Grid division coordinates
* - regionBounds: Boundary deformation data
* @returns base64 encoded string representing compressed warp state
*
* @example
* // 1. Get current warp state
* const warpState = warpvas.getWarpState();
*
* // 2. Serialize data
* const compressed = Warpvas.serializeWarpState(warpState);
*
* @see deserializeWarpState Restore compressed warp state
* @see getWarpState Retrieve current deformation data
*/
static serializeWarpState(warpState: WarpState): string;
/**
* Deserialize compressed warp state
*
* Restores warp deformation data from base64 string generated by serializeWarpState.
* The decompressed data can directly rebuild the texture's deformation state.
*
* @param base64String - base64 encoded string from serializeWarpState
* @returns {Object} Decompressed warp state containing:
* - splitPoints: Array of split coordinates (0-1 range)
* - boundData: 2D array of boundary deformation data per region
*
* @example
* // 1. Deserialize data
* const { splitPoints, boundData } = Warpvas.deserializeWarpState(compressedData);
*
* // 2. Apply deformation state
* warpvas.setWarpState(splitPoints, boundData);
*
* @see serializeWarpState Compress warp state
* @see setWarpState Apply deformation configuration
*/
static deserializeWarpState(base64String: string): WarpState;
/**
* Initialize split ratio points
*
* Creates initial grid of split points using relative coordinates (0-1 range)
* that partition the image into multiple deformable regions.
*
* @param rows - Horizontal divisions
* - Integer ≥ 1
* - Actual split lines = rows - 1
* - Example: rows=2 adds mid horizontal line
* - Default: 1 (no horizontal division)
*
* @param columns - Vertical divisions
* - Integer ≥ 1
* - Actual split lines = columns - 1
* - Example: columns=2 adds mid vertical line
* - Default: 1 (no vertical division)
*
* @returns Array of split coordinates as image size ratios (0-1)
*/
private _initializeSplitPoints;
/**
* Initialize original regions
*
* Partitions the image into multiple rectangular regions based on split ratio points.
* Each region contains four vertex coordinates in actual pixel positions (not ratios).
*
* @returns 2D array containing all region information:
* - 1st dimension: Row index
* - 2nd dimension: Column index
* - Each region contains four vertex coordinates (tl/tr/bl/br)
*/
private _initializeOriginalRegions;
/**
* Calculate sampling points for region boundaries
*
* Computes Bezier curve sampling positions based on region dimensions.
* Automatically adjusts point density to balance deformation quality and performance.
*
* @param region - Target region containing four vertices:
* - tl: Top-left
* - tr: Top-right
* - bl: Bottom-left
* - br: Bottom-right
*
* @returns Object containing sampling positions in two dimensions:
* - hts: Horizontal positions array (0-1 range)
* - vts: Vertical positions array (0-1 range)
*
* @remarks
* t-value in Bezier curves represents relative position:
* - t = 0: Curve start point
* - t = 1: Curve end point
* - 0 < t < 1: Intermediate point along the curve
*/
private _calculateSamplingPoints;
/**
* Initialize grid points within partition regions
*
* Generates grid points based on initial partition regions. These points will be used for:
* 1. Building reference grids during deformation
* 2. Calculating texture mapping relationships
* 3. Generating final deformation effects
*
* @returns 3D array containing all region grid points:
* - 1st dimension: Region row index
* - 2nd dimension: Region column index
* - 3rd dimension: List of grid points within the region
*/
private _initializeOriginalRegionPoints;
/**
* Initialize boundary Bezier curve control points
*
* Creates cubic Bezier curve control points for four boundaries of each partition region.
* Initial state produces straight-line curves, which can be bent by adjusting control points.
*
* @param regions - Array of partition regions, each containing four vertex coordinates
*
* @returns 3D array containing all boundary control points:
* - 1st dimension: Region row index
* - 2nd dimension: Region column index
* - 3rd dimension: Directional control points array (top/right/bottom/left)
* Each direction contains 4 points: start, first control, second control, end
*
* @remarks
* Cubic Bezier curve control points roles:
* - P0 (Start): Curve's initial position
* - P1 (First control): Controls tangent direction and curvature at start
* - P2 (Second control): Controls tangent direction and curvature at end
* - P3 (End): Curve's terminal position
*/
private _initializeBoundaryControlPoints;
/**
* Generate partition curve mesh within regions
*
* Creates internal mesh curves based on boundary Bezier curves. These curves form the deformation framework:
* 1. Establish deformation reference grids
* 2. Calculate texture mapping reference points
* 3. Achieve smooth deformation effects
*
* @param bounds - Bezier curve objects for region boundaries
* @param hts - Horizontal sampling positions array (0-1 range)
* @param vts - Vertical sampling positions array (0-1 range)
*
* @returns Object containing mesh curves in two orientations:
* - vertical: Array of vertical Bezier curves
* - horizontal: Array of horizontal Bezier curves
*
* @see _calculateSamplingPoints Calculate sampling positions
*/
private _generateRegionCurves;
/**
* Generate internal mesh curves for partition regions
*
* Creates internal grid curves based on boundary Bezier curves. These curves are used for:
* 1. Building deformation reference grids
* 2. Calculating texture mapping reference points
* 3. Achieving smooth deformation effects
*
* @param regionBoundaryCurves - 3D array of region boundary curves
* - 1st dimension: Row index
* - 2nd dimension: Column index
* - 3rd dimension: Four boundary Bezier curves per region (top/right/bottom/left)
*
* @returns 3D array containing all region mesh curves:
* - 1st dimension: Row index
* - 2nd dimension: Column index
* - 3rd dimension: Bezier curves in two orientations
* - vertical: Array of vertical curves
* - horizontal: Array of horizontal curves
*
* @see _generateRegionCurves Generate mesh curves for individual regions
* @see _calculateSamplingPoints Calculate sampling positions
*/
private _generateAllRegionCurves;
/**
* Set maximum ratio for deformation grid subdivision
*
* Controls the granularity of grid subdivision. Smaller values produce denser grids
* for finer deformation effects, while increasing computational load.
*
* @param splitUnit - Maximum subdivision ratio value
* - Range: Numerical value between 0-1
* - 0.1: Maximum grid unit equals 10% of image width
* - 0.05: Maximum grid unit equals 5% of image width
* - Values ≤0 or >1 will be reset to 1
*
* @returns Instance itself for method chaining
*
* @example
* // Set dense grid for finer deformation
* warpvas.setSplitUnit(0.05);
*
* // Set sparse grid for better performance
* warpvas.setSplitUnit(0.2);
*/
setSplitUnit(splitUnit: number): this;
/**
* Set calculation strategy for grid subdivision points
*
* Customizes grid subdivision point calculation method. Different strategies enable
* various deformation effects through alternative subdivision approaches.
*
* @param strategy - Subdivision strategy configuration object
* - name: Strategy identifier (customizable)
* - execute: Execution function receiving Warpvas instance
*
* @returns Instance itself for method chaining
*
* @example
* // Using custom strategy
* warpvas.setSplitStrategy({
* name: 'custom',
* execute: (warpvas) => {
* // Return custom grid points calculation
* return [[[{ x: 0, y: 0 }]]];
* }
* });
*
* @see Warpvas.strategy Default strategy implementation
*/
setSplitStrategy(strategy: Strategy): this;
/**
* Set size constraints for input canvas
*
* Restricts maximum dimensions of input canvas when processing large images.
* System will automatically scale images proportionally within constraints to
* improve performance and reduce memory consumption.
*
* @param limitSize - Size constraint configuration object
* - width?: number - Maximum width in pixels
* - height?: number - Maximum height in pixels
* - Pass undefined to remove constraints
*
* @returns Instance itself for method chaining
*
* @example
* // Constrain input to 1000x1000 pixels
* warpvas.setInputLimitSize({
* width: 1000,
* height: 1000
* });
*
* // Remove size constraints
* warpvas.setInputLimitSize(undefined);
*
* @remarks
* Performance recommendations:
* 1. For large images (>2000px), recommend setting appropriate constraints
* 2. Images maintain original aspect ratio when scaled
* 3. Uses cached canvas to avoid repeated scaling operations
*/
setInputLimitSize(limitSize: {
width?: number;
height?: number;
} | undefined): this;
/**
* Set size constraints for output canvas
*
* Restricts maximum dimensions of output canvas after deformation. When deformation results
* exceed size limits, system automatically scales output proportionally to prevent
* rendering failures due to memory constraints.
*
* @param limitSize - Size constraint configuration object
* - width?: number - Maximum width in pixels
* - height?: number - Maximum height in pixels
* - Pass undefined to remove constraints
*
* @returns Instance itself for method chaining
*
* @example
* // Constrain output to 2000x2000 pixels
* warpvas.setOutputLimitSize({
* width: 2000,
* height: 2000
* });
*
* // Remove size constraints (may cause large image rendering failures)
* warpvas.setOutputLimitSize(undefined);
*
* @remarks
* Performance recommendations:
* 1. Unconstrained deformation may exceed browser's Canvas size limits, causing blank output
* 2. Recommend setting appropriate constraints based on application scenarios
* 3. Output dimensions significantly impact rendering performance and memory usage
*/
setOutputLimitSize(limitSize: {
width?: number;
height?: number;
} | undefined): this;
/**
* Set rendering engine type
*
* Configures the rendering engine to use Canvas2D or WebGL mode. Mode comparison:
* - Canvas2D: Better compatibility (supports most browsers) but slower performance
* - WebGL: Better performance (GPU accelerated) for large images, but limited compatibility
*
* @returns Returns the instance itself for method chaining
*
* @remarks
* In safe rendering mode, the system will automatically fall back to Canvas2D
* when WebGL is unavailable or rendering fails
*
* @example
* // Enable Canvas2D rendering
* warpvas.setRenderingContext('2d');
*
* // Enable WebGL rendering
* warpvas.setRenderingContext('webgl');
*/
setRenderingContext(ctx: '2d' | 'webgl'): this;
/**
* Set rendering output canvas
*
* Specifies a fixed canvas for rendering output. Reusing the same canvas across multiple
* renders reduces memory allocation from canvas creation and improves performance.
*
* @param canvas - Target canvas element
*
* @returns Instance itself for method chaining
*
* @example
* // Reuse canvas in animation loop
* const canvas = document.createElement('canvas');
* warpvas.setRenderingCanvas(canvas);
*
* function animate() {
* // Update content on the same canvas each frame
* warpvas.render();
* requestAnimationFrame(animate);
* }
*
* @remarks
* WARNING: Avoid using the same canvas for both input and output, as this forces
* creating a temporary canvas copy before each render, significantly degrading performance
*/
setRenderingCanvas(canvas: HTMLCanvasElement): this;
/**
* Set rendering configuration options
*
* Configures various parameters for texture mapping rendering. Allows partial
* overriding of default configuration.
*
* @param options - Rendering configuration object
* - padding: number - Padding around output (pixels), default 0
* - enableAntialias: boolean - Enable/disable anti-aliasing, default true
* - enableSafeRendering: boolean - Safe rendering mode (WebGL only),
* auto-fallback to Canvas2D on failure, default true
* - enableContentDisplay: boolean - Show warped content, default true
* - enableGridDisplay: boolean - Show deformation grid, default false
* - enableGridVertexDisplay: boolean - Show grid vertices, default false
* - gridColor: { r: number, g: number, b: number, a: number } -
* Grid/vertex RGBA color object, default red (255,0,0,1)
*
* @returns Instance itself for method chaining
*
* @example
* // Configure rendering parameters
* warpvas.setRenderingConfig({
* padding: 10, // 10px padding
* enableAntialias: true, // Enable anti-aliasing
* enableSafeRendering: true, // Enable safe mode
* enableContentDisplay: true, // Display warped content
* enableGridDisplay: true, // Show deformation grid
* gridColor: { r: 0, g: 255, b: 0, a: 1 } // Green grid color
* });
*
* @remarks
* Performance recommendations:
* 1. Maintain enableSafeRendering=true in production environments
* 2. Padding helps prevent visual clipping during deformation
*/
setRenderingConfig(options: Partial<RenderingConfig>): this;
/**
* Get bounding box information of warped image
*
* Calculates boundary dimensions and offsets after deformation. The values include
* rendering configuration padding and can be used to properly size output canvas.
*
* @returns Bounding box information object containing:
* @returns offsetX - X-axis offset in pixels
* @returns offsetY - Y-axis offset in pixels
* @returns width - Total width including padding (pixels)
* @returns height - Total height including padding (pixels)
*
* @example
* // Get warped image dimensions
* const { width, height, offsetX, offsetY } = warpvas.getBoundingBoxInfo();
*
* // Apply dimensions to canvas
* canvas.width = width;
* canvas.height = height;
*
* // Adjust rendering position
* ctx.translate(offsetX, offsetY);
*/
getBoundingBoxInfo(): {
offsetX: number;
offsetY: number;
width: number;
height: number;
};
/**
* Clone source canvas element
*
* Creates a new canvas with identical dimensions and content from source canvas.
*
* @param canvas - Source canvas to clone
* @param width - Optional width override (default: source canvas width)
* @param height - Optional height override (default: source canvas height)
*
* @returns New canvas element with copied content
*/
private _cloneCanvas;
/**
* Create linear-like cubic Bezier curve
*
* Converts straight line between two points into cubic Bezier representation.
* Evenly distributes control points along the line to maintain visual linearity
* while preserving Bezier curve properties.
*
* @param p0 - Start point coordinates
* @param p1 - End point coordinates
*
* @returns Array of 4 control points representing cubic Bezier curve:
* [start, first control, second control, end]
*/
private _createLinearBezier;
/**
* Merge two Bezier curves
*
* Smoothly combines two adjacent Bezier curves into a single continuous curve.
* Primarily used during split point removal operations to maintain smooth transitions
* between merged curves.
*
* @param curve1Points - First curve's control points array [p0, p1, p2, p3]
* @param curve2Points - Second curve's control points array [p0, p1, p2, p3]
*
* @returns Merged Bezier curve's control points array [p0, p1, p2, p3]
*/
private _mergeBezierCurves;
/**
* Find connected vertex in deformation grid
*
* Retrieves position information of adjacent vertex connected to current boundary vertex.
* Essential for maintaining grid continuity during vertex manipulation operations.
*
* @param direction - Current edge direction
* - 'top': Top edge
* - 'bottom': Bottom edge
* - 'left': Left edge
* - 'right': Right edge
* @param position - Position on the edge
* - 'first': Start point of the edge
* - 'last': End point of the edge
*
* @returns Connected vertex information containing:
* - direction: Adjacent edge direction
* - position: Corresponding position on adjacent edge
*
* @see updateVertexCoord Used for updating vertex coordinates while maintaining grid continuity
*/
private _findConnectedVertex;
/**
* Update coordinates for a single vertex
*
* Maintains grid continuity by updating both:
* 1. Bezier curves on the vertex's two adjacent edges
* 2. Connected vertex's edge curves in deformation grid
*
* @param rowIndex - Row index of target vertex
* @param colIndex - Column index of target vertex
* @param type - Vertex position type (tl/tr/bl/br)
* @param coord - New coordinates { x, y }
* @param redistribute - Control point redistribution flag
* - true: Recalculate all control points (smooth transition)
* - false: Only update endpoints (preserve original curvature)
* - Default: true
*
* @see _findConnectedVertex Retrieve connected vertex information
* @see _createLinearBezier Create Bezier curve control points
*/
private _setSingleRegionVertexCoord;
/**
* Update coordinates for a warped texture vertex
*
* Moves specified vertex and automatically synchronizes all connected vertices
* to maintain grid continuity across deformation regions.
*
* @param rowIndex - Target region's row index (0-based)
* @param colIndex - Target region's column index (0-based)
* @param vertexPosition - Vertex position type
* - 'tl': Top-left
* - 'tr': Top-right
* - 'bl': Bottom-left
* - 'br': Bottom-right
* @param coord - New vertex coordinates { x, y }
* @param redistribute - Control point recalculation flag
* - true: Recalculate for smooth transition (default)
* - false: Preserve existing curve shape
*
* @returns Current instance for method chaining
*
* @example
* // Move top-left vertex of region (0,0) to (100,100)
* warpvas.updateVertexCoord(
* 0, // rowIndex
* 0, // colIndex
* 'tl', // vertexPosition
* { x: 100, y: 100 }, // New position
* true // Recalculate curves
* );
*
* @remarks
* Important considerations:
* 1. Vertex movement affects all connected vertices and curves
* 2. Setting redistribute=false preserves original curvature
* 3. Invalid indices will be silently ignored
*/
updateVertexCoord(rowIndex: number, colIndex: number, vertexPosition: `${VertexPosition}`, coord: Coord, redistribute?: boolean): this;
/**
* Update boundary curve coordinates for specified direction
*
* Modifies Bezier curve shape of region boundary by setting new control points,
* allowing curvature adjustments while maintaining grid continuity.
*
* @param rowIndex - Target region's row index (0-based)
* @param colIndex - Target region's column index (0-based)
* @param direction - Boundary direction to update
* - 'top': Top boundary
* - 'right': Right boundary
* - 'bottom': Bottom boundary
* - 'left': Left boundary
* @param coords - Bezier curve control points array containing:
* - p0: Start point coordinates
* - pm0: First control point coordinates
* - pm1: Second control point coordinates
* - p1: End point coordinates
*
* @returns Current instance for method chaining
*
* @example
* // Create S-shaped top boundary curve
* warpvas.updateRegionBoundCoords(
* 0, // rowIndex
* 0, // colIndex
* 'top', // direction
* [
* { x: 0, y: 0 }, // Start point
* { x: 30, y: 20 }, // Control point 1
* { x: 70, y: -20 }, // Control point 2
* { x: 100, y: 0 } // End point
* ]
* );
*
* @see updateVertexCoord For updating individual vertices
*/
updateRegionBoundCoords(rowIndex: number, colIndex: number, direction: `${Direction}`, coords: [p0: Coord, pm0: Coord, pm1: Coord, p1: Coord]): this;
/**
* Retrieve boundary curve control points for all regions
*
* Exports Bezier curve control point data for all deformation regions' boundaries.
* The returned data structure maintains full grid topology information for:
* 1. Serializing/deserializing warp states
* 2. Implementing undo/redo functionality
* 3. Cross-instance deformation synchronization
*
* @param callback - Custom data processor (optional)
* - rowIndex: Region's row index
* - colIndex: Region's column index
* - direction: Boundary direction ('top'|'right'|'bottom'|'left')
* - bezier: Bezier curve object containing control points
* - Default returns raw control point array
*
* @returns Three-dimensional array containing:
* - 1st dimension: Row indices
* - 2nd dimension: Column indices
* - 3rd dimension: Control points for four boundaries
* - top: Top boundary points [start, cp1, cp2, end]
* - right: Right boundary points
* - bottom: Bottom boundary points
* - left: Left boundary points
*
* @example
* // Get all boundary data with normalized coordinates
* const normalizedData = warpvas.forEachRegionBoundCoords(
* (row, col, dir, bezier) => bezier.points.map(p => ({
* x: p.x / sourceWidth,
* y: p.y / sourceHeight
* }))
* );
*
* @remarks
* Return format specification:
* [
* [ // Row 0
* { // Column 0
* top: [{x,y}, {x,y}, {x,y}, {x,y}], // 4 control points
* right: [{x,y}, {x,y}, {x,y}, {x,y}], // 4 control points
* bottom: [{x,y}, {x,y}, {x,y}, {x,y}], // 4 control points
* left: [{x,y}, {x,y}, {x,y}, {x,y}] // 4 control points
* },
* // More columns...
* ],
* // More rows...
* ]
*
* @see updateRegionBoundCoords For modifying boundary curves
*/
forEachRegionBoundCoords(callback?: (rowIndex: number, colIndex: number, direction: Direction, bezier: Bezier) => Coord[]): Record<Direction, Coord[]>[][];
/**
* Initialize Bezier curve objects for region boundaries
*
* Converts boundary control point data into Bezier curve instances while
* reusing shared boundary curves between adjacent regions.
*
* @param regionBoundsCoords - 3D array structure containing:
* - 1st dimension: Row indices
* - 2nd dimension: Column indices
* - 3rd dimension: Control points for four boundaries:
* - top: [start, cp1, cp2, end]
* - right: [start, cp1, cp2, end]
* - bottom: [start, cp1, cp2, end]
* - left: [start, cp1, cp2, end]
*
* @returns Curves array mirroring input structure:
* - 1st dimension: Row indices
* - 2nd dimension: Column indices
* - 3rd dimension: Four Bezier curve objects per region
*
* @see Bezier bezier-js library class for curve calculations
*/
private _initializeRegionBoundaryCurves;
/**
* Retrieve complete deformation state data
*
* @returns {WarpState} Deformation state object containing:
* - splitPoints: Array of split points with normalized coordinates (0-1 range)
* - regionBounds: 3D array of boundary control points for all regions
*
* @remarks
* Data structure specifications:
* - splitPoints: Normalized coordinates relative to original texture dimensions
* - regionBounds: Hierarchical array structure [rows][columns][boundaryDirections]
* - Each boundary contains exactly 4 control points in order: [p0, pm0, pm1, p1]
*
* @see setWarpState Apply saved deformation state
* @see resetWarpState Restore default grid configuration
*/
getWarpState(): WarpState;
/**
* Apply saved deformation state configuration
*
* Updates texture deformation using provided warp data, supporting:
* 1. State restoration from serialized data
* 2. Cross-instance deformation replication
* 3. Template-based warp applications
*
* @param splitPoints - Array of normalized split points (0-1 range)
* @param regionBounds - Boundary curve data (optional)
* - When provided: Directly sets boundary curves
* - When null: Generates linear boundaries from split points
*
* @returns Current instance for method chaining
*
* @example
* // 1. Apply complete warp state
* const data = sourceWarpvas.getWarpState();
* sourceWarpvas.setWarpState(data.splitPoints, data.regionBounds);
*
* // 2. Reset to non-warped state with central split
* warpvas.setWarpState([
* { x: 0.5, y: 0.5 } // Add central split point
* ]);
*
* @remarks
* Critical implementation details:
* 1. Split points must be normalized (0-1 range)
* 2. Automatic linear boundaries maintain grid continuity
* 3. Control point order: [p0, pm0, pm1, p1] per boundary
*
* @see getWarpState Retrieve current deformation state
* @see resetWarpState Restore default grid configuration
*/
setWarpState(splitPoints: Coord[], regionBounds?: Record<Direction, Coord[]>[][] | null): this;
/**
* Restore default grid configuration
*
* Resets texture deformation to initial grid state by:
* 1. Clearing all split points
* 2. Recreating straight-line boundaries
* 3. Rebuilding specified grid topology
*
* @param rows - Number of grid rows (default: 1)
* @param columns - Number of grid columns (default: 1)
*
* @returns Current instance for method chaining
*
* @example
* // 1. Reset to default 1x1 grid
* warpvas.resetWarpState();
*
* // 2. Reset to 3x2 grid
* warpvas.resetWarpState(3, 2);
*
* @see setWarpState Apply custom deformation state
* @see getWarpState Retrieve current deformation state
*/
resetWarpState(rows?: number, columns?: number): this;
/**
* Verify texture deformation status
*
* Determines if the texture is in its original undeformed state by checking:
* 1. Absence of split points (empty splitPoints array)
* 2. All boundaries remain linear (no Bezier curve deformation)
* 3. Boundary positions match original texture edges
*
* @returns {boolean}
* - true: Texture is in pristine undeformed state
* - false: Texture has deformation or splits
*/
isUnwarped(): boolean;
/**
* Detect hit position in warped texture
*
* Determines if a coordinate point lies within the deformed texture area
* and returns detailed positional metadata. Typical use cases include:
* 1. Implementing mouse interaction features
* 2. Validating click positions
* 3. Retri