UNPKG

fabric-texture

Version:

This JavaScript library enables fast and efficient image distortion transformations using Canvas 2D.

491 lines (490 loc) 16 kB
import type { Bezier } from 'bezier-js'; import { fabric } from 'fabric'; import { Texture, TransformData } from './texture.class'; import type { AbstractMode } from './abstract-mode.class'; /** * FabricTexture 实例的配置选项 * * 定义初始化 FabricTexture 实例时的配置选项,包括: * - 历史记录功能的开关 * - 历史记录变化的事件监听 * * @example * ```typescript * const fabricTexture = new FabricTexture(canvas, { * // 启用变形历史记录 * history: true, * * // 监听历史记录变化 * onHistoryChange: ({ undo, redo }) => { * // 根据历史记录状态更新 UI * } * }); * ``` */ type FabricTextureOptions = { /** * 是否启用变形操作的历史记录 * * 启用后,实例将维护一个变形状态的撤销/重做栈, * 使用户可以撤销或重做他们的变形操作。 * * @default false * * @remarks 启用历史记录会消耗额外的内存来存储过程变形数据。 */ history: boolean; /** * 历史记录变化时的回调函数 * * @param records 当前的历史记录状态 * @param records.undo 可撤销的变形记录数组 * @param records.redo 可重做的变形记录数组 * * @remarks undo 数组的第一项始终是初始状态 */ onHistoryChange: (records: { undo: TransformData[]; redo: TransformData[]; }) => void; }; /** * 贴图渲染选项 */ type RenderOptions = { /** * 是否跳过记录此次渲染的变形状态 * * 设为 true 时,本次渲染不会被添加到撤销栈中。 * 常用于以下场景: * - 临时预览渲染 * - 恢复历史状态时的渲染 * - 重置变形时的渲染 * * @default false */ withoutRecord: boolean; }; /** * Fabric.js 贴图变形工具类 * * 提供基于 Fabric.js 的图像变形功能,支持: * - 网格化变形:将图像划分为可调整的网格区域 * - 交互式编辑:支持鼠标拖拽调整变形效果 * - 实时预览:变形效果实时渲染 * - 历史记录:支持撤销/重做操作 * - 性能优化:自动处理大尺寸图像,优化渲染性能 * * @example * ```typescript * // 1. 创建 Fabric.js 画布 * const canvas = new fabric.Canvas('canvas'); * * // 2. 初始化贴图工具 * const fabricTexture = new FabricTexture(canvas, { * history: true, // 启用历史记录 * }); * * // 3. 准备需要变形的 fabric 元素对象,不限于图像元素 * const image = new fabric.Image(imageElement); * canvas.add(image); * * // 4. 进入编辑模式 * fabricTexture.enterEditing(image, null, new GridMode()); * * // 5. 完成编辑后退出 * fabricTexture.leaveEditing(); * ``` * * @remarks 使用前请确保已正确安装并引入 fabric.js * * @see AbstractMode 查看如何自定义变形模式 * @see Texture 了解底层变形实现 */ export declare class FabricTexture { /** * Fabric.js 画布实例 用于渲染和管理变形操作的画布对象 */ canvas: fabric.Canvas; /** * 实例配置选项 包含历史记录开关和变化监听器等配置 */ options: FabricTextureOptions; /** * 当前激活的变形模式 控制图像变形的交互方式和效果 * @default null */ mode: AbstractMode | null; /** * 核心变形引擎实例 负责处理底层的图像变形计算 * @default null */ texture: Texture | null; /** * 当前正在编辑的 Fabric 对象 可以是任何 Fabric.js 支持的对象类型(图片、路径等) * @default null */ target: fabric.Object | null; /** * 目标对象的画布表示 存储目标对象的原始图像数据 * @default null */ targetCanvas: HTMLCanvasElement | null; /** * 贴图的边界范围 记录变形区域的边界坐标,用于计算位置偏移 * @property {number} left - 左边界坐标 * @property {number} right - 右边界坐标 * @property {number} top - 上边界坐标 * @property {number} bottom - 下边界坐标 */ textureBoundary?: { left: number; right: number; top: number; bottom: number; }; /** * 贴图在水平方向的缩放比例 用于保持变形后的图像与原始尺寸的比例关系 * @default 1 */ textureScaleX: number; /** * 贴图在垂直方向的缩放比例 用于保持变形后的图像与原始尺寸的比例关系 * @default 1 */ textureScaleY: number; /** * 变形后的贴图对象 在画布上显示的实际图像对象 */ textureObject?: fabric.Image; /** * 网格路径元素列表 存储所有网格线的 Fabric.Path 对象 * @remarks 用于显示变形网格和处理交互 */ paths?: fabric.Path[]; /** * 贝塞尔曲线到路径对象的映射 用于快速查找曲线对应的路径对象 * @remarks 使用 WeakMap 避免内存泄漏 */ curvePathMap: WeakMap<Bezier, fabric.Path>; /** * 路径对象到贝塞尔曲线的映射 用于快速查找路径对应的曲线对象 * @remarks 使用 WeakMap 避免内存泄漏 */ pathCurveMap: WeakMap<fabric.Path, Bezier>; /** * 变形操作的历史记录 存储变形操作的撤销/重做状态 * @property {TransformData[]} undo - 可撤销的操作记录 * @property {TransformData[]} redo - 可重做的操作记录 */ records: { undo: Omit<TransformData, 'compressedCoordinates'>[]; redo: Omit<TransformData, 'compressedCoordinates'>[]; }; /** * 普通渲染的清理回调函数 * 存储渲染过程中创建的交互元素的清理函数。 * 在下次渲染前或离开编辑态时会被调用,可用于清理上一次渲染的交互元素。 * * @private * @type {(() => void) | void} */ private _renderReturnCallback?; /** * 脏渲染的清理回调函数 * 存储脏渲染(结构发生变化,比如添加或删除了区域分割点)时创建的交互元素的清理函数。 * 在下次脏渲染前或离开编辑态时会被调用,可用于清理上一次渲染的交互元素。 * * @private * @type {(() => void) | void} */ private _dirtyRenderReturnCallback?; /** * 下一帧渲染的请求标识 * 存储 requestAnimationFrame 返回的标识符。 * 用于在需要时取消已计划但尚未执行的渲染操作, * 避免不必要的渲染和性能浪费。 * * @private * @type {number | undefined} */ private _nextFrameRender; /** * 创建 FabricTexture 实例 * * 初始化一个贴图变形工具实例。该实例将与指定的 Fabric.js 画布关联, * 用于处理画布上的图像变形操作。 * * @param canvas - Fabric.js 画布实例 * @param [options] - 配置选项 * @param [options.history=false] - 是否启用操作历史记录 * @param [options.onHistoryChange] - 历史记录变化时的回调函数 * * @example * ```typescript * const canvas = new fabric.Canvas('canvas'); * const texture = new FabricTexture(canvas); * ``` * * @remarks * 1. 创建实例后,需要调用 enterEditing 方法才能开始编辑 * 2. 启用历史记录会消耗额外的内存,请根据实际需求选择是否启用 */ constructor(canvas: fabric.Canvas, options?: Partial<FabricTextureOptions>); /** * 渲染贴图变形效果 * * 将当前的变形状态渲染到画布上。 * * @param [dirty=true] - 是否为脏渲染,脏渲染会导致 _dirtyRenderReturnCallback 回调执行 * @param [options] - 渲染配置选项 * @param [options.withoutRecord=false] - 是否跳过记录此次渲染的变形状态 * * @example * ```typescript * // 普通渲染(仅网格分割点位置变化) * fabricTexture.render(false); * * // 脏渲染(网格结构发生变化,如添加或删除了分割点) * fabricTexture.render(true); * * // 临时预览渲染(不记录历史) * fabricTexture.render(true, { withoutRecord: true }); * ``` * * @remarks * 1. 脏渲染会重建整个网格结构,性能消耗较大 * 2. 非脏渲染仅更新现有网格的控制点位置,性能消耗较小 * 3. 如果不需要记录历史,建议设置 withoutRecord 为 true * * @see requestRender 性能优化版本的渲染方法 */ render(dirty?: boolean, options?: Partial<RenderOptions>): void; /** * 在下一帧渲染贴图变形效果(性能优化版本) * * 使用 requestAnimationFrame 延迟渲染到下一帧,可以: * 1. 避免短时间内的重复渲染 * 2. 优化连续变形时的性能 * 3. 保持画面流畅度 * * @param [dirty=true] - 是否为脏渲染,脏渲染会导致 _dirtyRenderReturnCallback 回调执行 * @param [callback] - 渲染完成后的回调函数 * @param [options] - 渲染配置选项 * @param [options.withoutRecord=false] - 是否跳过记录此次渲染的变形状态 * * @example * ```typescript * // 基础用法 * fabricTexture.requestRender(); * * // 带回调的用法 * fabricTexture.requestRender(true, () => { * console.log('渲染完成'); * }); * * // 连续变形时的优化用法 * function onDragging() { * fabricTexture.requestRender(false, null, { * withoutRecord: true // 拖拽过程中不记录历史 * }); * } * * function onDragEnd() { * fabricTexture.render(true); // 拖拽结束时记录一次历史 * } * ``` * * @remarks * 1. 此方法会自动取消上一次尚未执行的渲染请求 * 2. 适合用于处理连续的变形操作,如拖拽控制点 * 3. 对于关键状态的保存,建议使用同步的 render 方法 * * @see render 同步渲染方法 */ requestRender(dirty?: boolean, callback?: () => void, options?: Partial<RenderOptions>): void; /** * 提取当前变形状态的数据 * * 获取当前图像的变形状态数据。 * * @returns * - 如果当前不在编辑状态,返回 null * - 否则返回包含以下属性的对象: * - data: 原始变形数据 * - compressedData: 压缩后的字符串形式数据 */ serialize(): { data: TransformData; compressedData: string; } | null; /** * 进入图像编辑模式 * * 使指定的 Fabric 对象进入变形编辑状态。 * * @param object - 要编辑的 Fabric 对象(如图片、路径等) * @param [sourceCanvas] - 可选的源画布,用于特殊渲染需求。如果为 null,将使用 object 生成的画布 * @param mode - 变形模式实例,决定了变形的交互方式和效果 * @param [beforeFirstRender] - 首次渲染前的回调函数,可用于初始化变形引擎的配置 * * @example * ```typescript * fabricTexture.enterEditing( * image, * null, * new GridMode(), * (texture) => { * // 设置显示分割网格线 * texture.setRenderOptions({ showGrid: true }); * } * ); * ``` * * @see leaveEditing 退出编辑模式 */ enterEditing(object: fabric.Object, sourceCanvas: HTMLCanvasElement | null, mode: AbstractMode, beforeFirstRender?: (texture: Texture) => void): void; /** * 退出图像编辑模式 * * 结束当前对象的变形编辑状态。 * * @example * ```typescript * // 完成编辑后退出 * fabricTexture.leaveEditing(); * * // 典型的编辑流程 * try { * // 1. 进入编辑模式 * fabricTexture.enterEditing(image, null, new GridMode()); * * // 2. 进行编辑操作... * * // 3. 保存编辑结果 * const result = fabricTexture.serialize(); * * // 4. 退出编辑模式 * fabricTexture.leaveEditing(); * } catch (error) { * console.error('编辑过程出错:', error); * fabricTexture.leaveEditing(); // 确保清理资源 * } * ``` * * @see enterEditing 进入编辑模式 */ leaveEditing(): void; /** * 记录当前变形状态 * * 将当前的变形状态保存到历史记录中。 * * @remarks * 1. 仅在启用了历史记录功能时生效(options.history = true) * 2. 每次记录都会创建状态的深拷贝,注意内存占用 * * @see undo 撤销操作 * @see redo 重做操作 */ record(): void; /** * 撤销上一步变形操作 * * 将变形状态回退到上一个记录点。 * * @example * ```typescript * // 基础用法 * fabricTexture.undo(); * * // 配合快捷键使用 * document.addEventListener('keydown', (e) => { * if (e.ctrlKey && e.key === 'z') { * fabricTexture.undo(); * } * }); * ``` * * @remarks * 1. 如果撤销栈为空或只有初始状态,此操作无效 * 2. 撤销操作本身不会产生新的历史记录 * * @see redo 重做已撤销的操作 */ undo(): void; /** * 重做已撤销的变形操作 * * 重新应用之前撤销的变形状态。 * * @example * ```typescript * // 基础用法 * fabricTexture.redo(); * * // 配合快捷键使用 * document.addEventListener('keydown', (e) => { * if (e.ctrlKey && e.key === 'y') { * fabricTexture.redo(); * } * }); * ``` * * @remarks * 1. 如果重做栈为空,此操作无效 * 2. 重做操作本身不会产生新的历史记录 * 3. 执行新的变形操作会清空重做栈 * * @see undo 撤销操作 */ redo(): void; /** * 重置变形状态 * * 将图像重置到指定状态: * - 当 keepHistory=true 时:清除所有变形效果,但保留操作记录 * - 当 keepHistory=false 时:回退到初始状态,并将后续状态移入重做栈 * * @param keepHistory - 是否保留历史记录 * - true: 清除变形但保留历史,可用于临时预览原始状态 * - false: 回退到初始状态,后续状态可通过重做恢复 * * @example * ```typescript * // 1. 清除变形但保留历史记录 * fabricTexture.reset(true); * * // 2. 回退到初始状态,保留重做可能 * fabricTexture.reset(false); * * // 3. 配合撤销/重做使用 * fabricTexture.reset(false); * if (fabricTexture.canRedo()) { * // 可以通过 redo() 恢复之前的状态 * fabricTexture.redo(); * } * ``` * * @remarks * 1. keepHistory=true 时: * - 生成新的历史记录 * - 清空重做栈 * - 适合用于临时预览或确定放弃变形 * * 2. keepHistory=false 时: * - 不生成新的历史记录 * - 保留重做可能性 * - 适合用于需要保留恢复可能的场景 * * 3. 在以下情况下方法无效: * - 当前不在编辑状态(texture 为 null) * - 当前已经是初始状态(keepHistory=true 时) * * @see undo 单步撤销操作 * @see redo 重做已撤销的操作 * @see serialize 保存当前变形状态 */ reset(keepHistory?: boolean): void; } export {};