UNPKG

fabric-texture

Version:

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

1,606 lines (1,029 loc) 34.8 kB
[**fabric-texture**](../../README.md) *** # Class: Texture 贴图类 贴图类可以基于图像源创建其对应的变形工具对象实例, 该实例对象可以结合内部方法可以对图像施加变形并产出变形后的图形画布。 ## Example ```ts const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); if (!ctx) return; // 绘制矩形 ctx.fillRect(0, 0, canvas.width, canvas.height); // 创建 Texture 贴图类实例,传入画布作为图像源 const texture = new Texture(canvas); // 将画布图像左上角移动到(50,50)的位置 texture.setVertexCoord(0, 0, 'tl', { x: 50, y: 50 }); // 生成变形后的图像画布并加入文档 const textureCanvas = texture.create(); document.body.appendChild(textureCanvas); ``` ## Constructors ### new Texture() > **new Texture**(`source`, `rows`, `columns`): [`Texture`](Texture.md) 构造贴图对象实例 创建一个新的贴图变形工具实例。你可以传入一个图像或画布作为源, 并可以选择性地设置初始的网格分割数量。 #### Parameters ##### source 图像源,可以是 HTMLImageElement 或 HTMLCanvasElement 如果传入图像,会自动创建一个新画布并将图像绘制其中 如果传入画布,将直接使用该画布作为源 `HTMLCanvasElement` | `HTMLImageElement` ##### rows `number` = `1` 初始横向分割数量 - 必须是大于等于 1 的整数 - 值为 1 时不进行横向分割 - 值为 2 时会在中间添加一条分割线 - 默认值: 1 ##### columns `number` = `1` 初始纵向分割数量 - 必须是大于等于 1 的整数 - 值为 1 时不进行纵向分割 - 值为 2 时会在中间添加一条分割线 - 默认值: 1 #### Returns [`Texture`](Texture.md) #### Example ```ts // 用法:使用图像创建实例 const img = new Image(); img.src = 'example.jpg'; img.onload = () => { const texture = new Texture(img); }; // 用法:使用画布创建实例并设置 2x2 的初始网格分割 const canvas = document.createElement('canvas'); const texture = new Texture(canvas, 2, 2); ``` ## Properties ### areaBoundCurves > **areaBoundCurves**: `Record`\<`Direction`, `Bezier`\>[][] = `[]` 区域边界曲线 存储每个分割区域四条边的贝塞尔曲线对象。 #### Remarks 请勿直接操作该列表对象,而是通过 setBoundCoords 方法调整指定曲线以实现区域边界的弯曲变形效果。 #### Example ```ts // 调整第一个区域的上边界曲线 texture.setBoundCoords(0, 0, 'top', [ { x: 0, y: 0 }, { x: 100, y: 100 }, { x: 200, y: 100 }, { x: 300, y: 0 } ]); ``` *** ### initialMeshPoints > **initialMeshPoints**: `Coord`[][][] = `[]` 初始网格点坐标 三维数组,存储变形前每个区域内部的网格点坐标。 这些点用于计算变形时的图像映射关系。 数组结构:[区域行][区域列][网格点列表] *** ### initialSplitAreas > **initialSplitAreas**: `Area`[][] = `[]` 变形前的区域信息 二维数组,存储变形前每个分割区域的四个顶点坐标。 数组结构:[区域行][区域列],每个区域包含左上(tl)、右上(tr)、左下(bl)、右下(br)四个顶点。 #### Example ```ts // 访问第一个区域的左上角坐标 const topLeft = texture.initialSplitAreas[0][0].tl; ``` *** ### mesh > **mesh**: `object`[][] = `[]` 变形后的网格曲线 存储变形后每个区域的网格线条,包括垂直和水平方向的贝塞尔曲线。 这些曲线决定了最终图像的变形效果。 *** ### meshPoints > **meshPoints**: `Coord`[][][] = `[]` 变形后的网格点 存储变形后的网格点坐标。这些点的位置由分割策略计算得出, 不同的分割策略会产生不同的变形效果。 #### See Strategy 查看分割策略的详细说明 *** ### renderEngine > **renderEngine**: `"canvas"` \| `"webgl"` = `'webgl'` 渲染引擎类型 指定使用的渲染方式,支持 'canvas' 或 'webgl'。 WebGL 模式性能更好,当设置了安全渲染配置时,在不支持 WebGL 的环境下会自动降级使用 Canvas。 #### Default ```ts 'webgl' ``` #### Example ```ts // 强制使用 Canvas 2D 渲染 texture.useCanvasRender(); ``` *** ### renderOptions > **renderOptions**: `TextureRenderOptions` 渲染选项 控制渲染过程的各种参数,包括留白、抗锯齿、调试网格显示等。 可以通过 setRenderOptions 方法动态修改这些选项。 #### See TextureRenderOptions 查看所有可用的渲染选项 #### Example ```ts texture.setRenderOptions({ padding: 20, // 设置20像素留白 showGrid: true, // 显示调试网格 antialias: true // 启用抗锯齿 }); ``` *** ### source > **source**: `HTMLCanvasElement` 图像源画布对象 存储原始图像数据的画布。如果构造函数传入的是 HTMLImageElement, 会自动创建一个新的画布并将图像绘制到其中,以避免对原始图像的修改。 #### Example ```ts const img = new Image(); img.src = 'example.jpg'; img.onload = () => { const texture = new Texture(img); // 会自动创建画布 }; ``` *** ### splitRatioPoints > **splitRatioPoints**: `Coord`[] = `[]` 图像分割点的相对位置列表 存储图像分割点的相对坐标(范围0-1)。这些点将图像划分为多个可变形区域, 每个分割点的坐标都是相对于图像尺寸的比例值。 #### Remarks 请勿直接操作该列表,而是通过 addSplitPoint 方法来添加分割点。 *** ### splitStrategy > **splitStrategy**: `Strategy` 分割点计算策略 定义如何计算变形区域内部的网格点位置。 默认使用内置的扭曲策略,你也可以通过 setSplitStrategy 方法设置自定义策略。 #### Example ```ts // 设置自定义分割策略 texture.setSplitStrategy({ name: 'custom', execute: (texture) => { // 返回自定义的网格点计算结果 return [[[{ x: 0, y: 0 }]]]; } }); ``` *** ### splitUnit > **splitUnit**: `number` = `0.05` 网格分割比例 控制网格的密度,值范围 0-1。这个值越小,网格越密,变形效果越精细, 但同时也会增加计算量。例如,值为 0.1 时,每个网格的最大尺寸为图像宽度的 10%。 #### Default ```ts 0.05 ``` #### Example ```ts // 设置更密的网格以获得更精细的变形效果 texture.setSplitUnit(0.02); ``` ## Accessors ### maxSplitUnitPixel #### Get Signature > **get** **maxSplitUnitPixel**(): `number` 获取最大分割像素大小 计算当前贴图允许的最大网格分割尺寸(以像素为单位)。 这个值由 splitUnit(分割比例)和图像宽度共同决定。 ##### Example ```ts // 假设图像宽度为 1000px,splitUnit 为 0.1 const maxSize = texture.maxSplitUnitPixel; // 返回 100px ``` ##### See splitUnit 查看分割比例的设置 ##### Returns `number` 返回最大分割像素值 - 当 splitUnit 为 0.1 时,返回图像宽度的 10% - 当 splitUnit 为 0.05 时,返回图像宽度的 5% *** ### scale #### Get Signature > **get** **scale**(): `object` 获取画布的实际缩放比率 返回当前画布相对于原始尺寸的缩放比例。 缩放比例由输入限制和输出限制共同影响: - 输入限制:处理大尺寸图像时的自动缩放 - 输出限制:防止生成过大画布时的自动缩放 ##### Example ```ts const { x, y } = texture.scale; console.log(`当前画布被缩放至原始尺寸的 ${x * 100}%`); ``` ##### Returns `object` 返回 x 和 y 方向的缩放比例 - 值为 1 表示原始大小 - 值小于 1 表示被缩小 - x 和 y 始终保持相同以避免变形 ###### x > **x**: `number` ###### y > **y**: `number` ## Methods ### addSplitPoint() > **addSplitPoint**(`rowIndex`, `colIndex`, `splitPoint`, `tolerate`): `void` 在指定位置添加分割点 在贴图的指定区域添加一个新的分割点,将区域分割成更小的子区域。 #### Parameters ##### rowIndex `number` 目标区域的行索引 ##### colIndex `number` 目标区域的列索引 ##### splitPoint `Coord` 分割点的坐标 - x: X坐标(像素) - y: Y坐标(像素) ##### tolerate `number` = `0.05` 分割点的容差值(默认0.05) - 范围:0-1之间 - 当分割点距离边界的距离小于容差时,会自动吸附到边界 - 较大的容差值可以防止在边界附近产生过小的分割区域 #### Returns `void` #### Example ```ts // 在第一个区域(0,0)的中心位置添加分割点,分割后该区域会变成2x2的区域 const area = texture.initialSplitAreas[0][0]; texture.addSplitPoint( 0, // rowIndex 0, // colIndex { // 区域中心点 x: (area.tl.x + area.br.x) / 2, y: (area.tl.y + area.br.y) / 2 }, 0.1 // 10%的容差 ); ``` #### Remarks 注意事项: 1. 分割点会根据容差值自动吸附到边界 2. 添加分割点会影响相邻区域的边界形状,特别是已扭曲的区域 3. 过多的分割点可能会影响性能 #### See removeSplitPoints 删除分割点 *** ### containsPoint() > **containsPoint**(`point`): `null` \| \{ `after`: `Coord`[]; `before`: `Coord`[]; `clickPart`: `0` \| `1`; `col`: `number`; `colIndex`: `number`; `row`: `number`; `rowIndex`: `number`; \} 检测指定坐标点是否在变形后的贴图区域内 判断一个坐标点是否落在变形后的贴图区域内,并返回详细的位置信息。 这个方法通常用于: 1. 实现鼠标交互功能 2. 检测点击位置 3. 获取点击区域的详细信息 #### Parameters ##### point `Coord` 要检测的坐标点 - x: X坐标(像素) - y: Y坐标(像素) #### Returns `null` \| \{ `after`: `Coord`[]; `before`: `Coord`[]; `clickPart`: `0` \| `1`; `col`: `number`; `colIndex`: `number`; `row`: `number`; `rowIndex`: `number`; \} 如果点在区域内,返回包含以下信息的对象: - rowIndex: 所在区域的行索引 - colIndex: 所在区域的列索引 - row: 所在网格的行号 - col: 所在网格的列号 - before: 原始网格的四个顶点坐标 [左上,右上,右下,左下] - after: 变形后网格的四个顶点坐标 [左上,右上,右下,左下] - clickPart: 归属区域的哪个三角图元(0:上三角图元, 1:下三角图元) 如果点不在变形图像区域内,返回 null #### Example ```ts // 检测鼠标点击位置 canvas.addEventListener('click', (e) => { const info = texture.contains({ x: e.clientX - canvas.offsetLeft, y: e.clientY - canvas.offsetTop }); if (info) { console.log('点击位置在区域内:', info); } }); ``` *** ### create() > **create**(): `HTMLCanvasElement` 生成变形后的贴图画布 根据当前的变形参数,生成一个新的画布或在指定画布上渲染变形后的图像。 #### Returns `HTMLCanvasElement` 返回变形后的画布元素 #### Throws - 当渲染失败且未启用安全模式时抛出错误 - 当画布创建失败时抛出错误 #### Example ```ts const canvas = texture.create(); document.body.appendChild(canvas); ``` #### Remarks 性能建议: 1. 如果需要频繁更新,建议使用 useInstanceCanvas 复用输出画布 2. 如果遇到大图变形的性能问题,可以尝试切换渲染引擎或使用 createWithWorker #### See - useInstanceCanvas 设置复用画布 - createWithWorker 在 Worker 中异步渲染 *** ### createWithWorker() > **createWithWorker**(): `Promise`\<`HTMLCanvasElement`\> 在 Web Worker 中异步生成变形贴图画布 在独立线程中执行贴图变形和渲染操作,避免阻塞主线程。 #### Returns `Promise`\<`HTMLCanvasElement`\> 返回一个 Promise,解析为渲染后的画布元素 #### Throws - 当 Worker 创建失败时抛出错误 - 当渲染失败且未启用安全模式时抛出错误 - 当画布创建失败时抛出错误 #### Example ```ts // 异步渲染并等待结果 try { const canvas = await texture.createWithWorker(); document.body.appendChild(canvas); } catch (error) { console.error('渲染失败:', error); } ``` #### Remarks 注意事项: 1. 相比 create 方法,此方法会消耗更多内存 2. 首次调用时可能有短暂延迟(Worker 初始化) 3. 不要在高频率循环中使用此方法 #### See - create 同步渲染方法 - setRenderOptions 设置渲染选项 *** ### destroy() > **destroy**(): `void` 销毁贴图实例 清理实例中的缓存和引用,释放内存。在不再需要贴图实例时调用此方法。 #### Returns `void` #### Example ```ts // 销毁贴图实例 texture.destroy(); texture = null; // 解除引用 ``` *** ### forEachSplitArea() > **forEachSplitArea**(`handler`): `void` 遍历变形网格中的所有四边形单元 遍历贴图变形网格中的每个四边形单元,并提供其变形前后的顶点信息。 #### Parameters ##### handler (`newVertexs`, `oldVertexs`, `row`, `col`, `rowIndex`, `colIndex`) => `void` 处理每个四边形单元的回调函数 接收以下参数: - newVertexs: 变形后的四个顶点坐标 [左上,右上,右下,左下] - oldVertexs: 变形前的四个顶点坐标 [左上,右上,右下,左下] - row: 在当前区域内的行索引 - col: 在当前区域内的列索引 - rowIndex: 所属变形区域的行索引 - colIndex: 所属变形区域的列索引 #### Returns `void` #### Example ```ts // 遍历所有网格单元并打印其位置信息 texture.forEachSplitArea((newVertexs, oldVertexs, row, col, rowIndex, colIndex) => { console.log(`区域[${rowIndex},${colIndex}] 所在内部分割的网格位置[${row},${col}]:`); console.log('变形前:', oldVertexs); console.log('变形后:', newVertexs); }); ``` *** ### getAreaBoundCoords() > **getAreaBoundCoords**(`callback`): `Record`\<`Direction`, `Coord`[]\>[][] 获取所有区域的边界曲线数据 导出所有变形区域的边界曲线控制点数据。 #### Parameters ##### callback (`rowIndex`, `colIndex`, `direction`, `bezier`) => `Coord`[] 自定义数据处理函数(可选) - rowIndex: 区域的行索引 - colIndex: 区域的列索引 - direction: 边界方向('top'|'right'|'bottom'|'left') - bezier: 贝塞尔曲线对象,包含控制点信息 - 默认返回原始控制点数组 #### Returns `Record`\<`Direction`, `Coord`[]\>[][] 返回三维数组,包含所有区域边界的控制点数据: - 第一维:区域行索引 - 第二维:区域列索引 - 第三维:该区域四个方向的控制点数组 - top: 上边界的控制点 [起点,控制点1,控制点2,终点] - right: 右边界的控制点 - bottom: 下边界的控制点 - left: 左边界的控制点 #### Remarks 返回的控制点数组格式: [ [ // 第一行区域 { // 第一列区域 top: [{x,y}, {x,y}, {x,y}, {x,y}], // 4个控制点 right: [{x,y}, {x,y}, {x,y}, {x,y}], // 4个控制点 bottom: [{x,y}, {x,y}, {x,y}, {x,y}], // 4个控制点 left: [{x,y}, {x,y}, {x,y}, {x,y}] // 4个控制点 }, // ... 更多列 ], // ... 更多行 ] #### See - setBoundCoords 设置单个区域的边界曲线 - getTransformData 获取完整的变形数据 *** ### getBoundingBoxInfo() > **getBoundingBoxInfo**(): `object` 获取变形后图像的包围盒信息 计算变形后图像的边界范围和偏移量。 #### Returns `object` 包围盒信息 offsetX - X轴偏移量 offsetY - Y轴偏移量 width - 包围盒的宽度(像素),包含 padding height - 包围盒的高度(像素),包含 padding ##### height > **height**: `number` ##### offsetX > **offsetX**: `number` ##### offsetY > **offsetY**: `number` ##### width > **width**: `number` #### Example ```ts // 获取变形后图像的尺寸和位置信息 const { width, height, offsetX, offsetY } = texture.getBoundingBoxInfo(); // 使用这些信息设置画布尺寸 canvas.width = width; canvas.height = height; // 调整图像位置 ctx.translate(offsetX, offsetY); ``` #### See setRenderOptions 设置 padding 值 *** ### getTransformData() > **getTransformData**(): `TransformData` 获取当前贴图的变形数据 导出当前贴图的变形状态,包括分割点和边界曲线数据。 这些数据可以用于: 1. 保存当前的变形状态 2. 在其他贴图上复制相同的变形效果 3. 序列化变形数据用于传输或存储 #### Returns `TransformData` 变形数据对象 - splitRatioPoints: 分割点数组,每个点的坐标都是相对于原始图像尺寸的比例值(0-1) - areaBound: 边界曲线数据,包含每个分割区域四条边的贝塞尔曲线控制点 #### See setTransformData 使用变形数据设置贴图 *** ### isNoneTransform() > **isNoneTransform**(): `boolean` 检查贴图是否处于初始未变形状态 判断当前贴图是否完全处于未变形的初始状态。 满足以下所有条件时返回 true: 1. 没有任何分割点(splitRatioPoints.length === 0) 2. 所有边界都是直线(没有曲线变形) 3. 边界位置与原始图像边界重合 #### Returns `boolean` - true: 贴图处于完全未变形的初始状态 - false: 贴图已经发生了变形或分割 *** ### removeSplitPoints() > **removeSplitPoints**(`list`): `void` 删除指定位置的分割点 删除一个或多个分割点,并自动合并相关的区域。 #### Parameters ##### list \[`number`, `number`\][] 要删除的分割点位置数组 - 每个元素是一个包含行列索引的元组 [行索引, 列索引] - 行列索引从 0 开始计数 #### Returns `void` #### Example ```ts // 删除区域分割点 texture.removeSplitPoints([ [1, 1], // 删除第2行第2列的分割点 [2, 2], // 删除第3行第3列的分割点 ]); ``` #### Remarks 重要说明: 1. 以下情况的删除操作无效: - 图像四个角的顶点 - 超出区域范围的点 - 不存在的分割点 2. 删除分割点的处理顺序: - 先合并行(从下往上) - 再合并列(从右往左) - 自动处理边界曲线的平滑过渡 3. 性能考虑: - 建议一次性删除多个分割点,而不是多次调用删除单个点 #### See addSplitPoint 添加分割点 *** ### resetTransformData() > **resetTransformData**(`rows`, `columns`): [`Texture`](Texture.md) 重置贴图的变形状态 清除所有变形效果,将贴图重置为指定行列数的网格。 这个方法会: 1. 清除所有分割点 2. 重置所有边界为直线 3. 重新创建指定数量的网格 #### Parameters ##### rows `number` = `1` 重置后的网格行数,默认为 1 ##### columns `number` = `1` 重置后的网格列数,默认为 1 #### Returns [`Texture`](Texture.md) 返回实例本身,支持链式调用 #### Example ```ts // 重置为默认状态(1x1 网格) texture.resetTransformData(); // 重置为 2x3 的网格 texture.resetTransformData(2, 3); ``` #### See setTransformData 设置变形数据 *** ### setBoundCoords() > **setBoundCoords**(`rowIndex`, `colIndex`, `direction`, `coords`): [`Texture`](Texture.md) 更新某个方向边的曲线坐标 修改区域边界的贝塞尔曲线形状。通过设置新的控制点, 可以改变边界的弯曲程度和形状,同时保持与相邻区域的连接。 #### Parameters ##### rowIndex `number` 目标区域的行索引(从0开始) ##### colIndex `number` 目标区域的列索引(从0开始) ##### direction `Direction` 要更新的边界方向 - 'top': 上边界 - 'right': 右边界 - 'bottom': 下边界 - 'left': 左边界 ##### coords \[`Coord`, `Coord`, `Coord`, `Coord`\] 贝塞尔曲线的4个控制点坐标 - p0: 起始点坐标 - pm0: 第一控制点坐标 - pm1: 第二控制点坐标 - p1: 终点坐标 #### Returns [`Texture`](Texture.md) 返回实例本身,支持链式调用 #### Example ```ts // 创建一个S形的上边界曲线 texture.setBoundCoords( 0, // rowIndex 0, // colIndex 'top', // direction [ { x: 0, y: 0 }, // 起始点 { x: 30, y: 20 }, // 控制点1 { x: 70, y: -20 }, // 控制点2 { x: 100, y: 0 } // 终点 ] ); ``` #### See setVertexCoord 用于更新单个顶点 *** ### setInputLimitSize() > **setInputLimitSize**(`limitSize`): [`Texture`](Texture.md) 设置输入画布的尺寸限制 当处理大尺寸图像时,可以通过此方法限制输入画布的最大尺寸, 系统会自动将图像等比缩放到限制范围内进行处理,以提高性能和减少内存占用。 #### Parameters ##### limitSize 尺寸限制配置对象 - width?: number - 最大宽度(像素) - height?: number - 最大高度(像素) - 传入 undefined 则取消限制,使用原始尺寸 `undefined` | \{ `height`: `number`; `width`: `number`; \} #### Returns [`Texture`](Texture.md) 返回实例本身,支持链式调用 #### Example ```ts // 限制输入图像最大尺寸为 1000x1000 texture.setInputLimitSize({ width: 1000, height: 1000 }); // 只限制宽度,高度自动等比缩放 texture.setInputLimitSize({ width: 1000 }); // 取消尺寸限制 texture.setInputLimitSize(undefined); ``` #### Remarks 性能建议: 1. 对于大尺寸图像(如>2000px),建议设置合适的限制以提高性能 2. 图像会被等比缩放,保持原始宽高比 3. 实际处理时会使用缓存画布,避免重复缩放 *** ### setOutputLimitSize() > **setOutputLimitSize**(`limitSize`): [`Texture`](Texture.md) 设置输出画布的尺寸限制 限制变形后输出画布的最大尺寸。当变形导致画布尺寸过大时, 系统会自动将结果等比缩放到限制范围内,避免因内存限制导致渲染失败。 #### Parameters ##### limitSize 尺寸限制配置对象 - width?: number - 最大宽度(像素) - height?: number - 最大高度(像素) - 传入 undefined 则取消限制,使用原始尺寸 `undefined` | \{ `height`: `number`; `width`: `number`; \} #### Returns [`Texture`](Texture.md) 返回实例本身,支持链式调用 #### Example ```ts // 限制输出画布最大尺寸为 2000x2000 texture.setOutputLimitSize({ width: 2000, height: 2000 }); // 只限制宽度,高度自动等比缩放 texture.setOutputLimitSize({ width: 2000 }); // 取消尺寸限制(注意:可能导致大尺寸图像渲染失败) texture.setOutputLimitSize(undefined); ``` #### Remarks 重要提示: 1. 不设置限制时,变形后的大尺寸图像可能超出浏览器的 Canvas 尺寸限制导致渲染失败或显示空白 2. 建议根据实际使用场景设置合理的限制值 3. 输出尺寸会影响渲染性能和内存占用 *** ### setRenderOptions() > **setRenderOptions**(`options`): [`Texture`](Texture.md) 设置渲染配置选项 配置贴图渲染的各种参数。 #### Parameters ##### options `Partial`\<`TextureRenderOptions`\> 渲染配置对象,可以部分覆盖默认配置 - padding: number - 留白距离(像素),默认 0 - antialias: boolean - 抗锯齿效果,默认 true - safe: boolean - 安全渲染模式(仅WebGL模式有效,WebGL失败时自动降级),默认 true - showTexture: boolean - 是否显示贴图,默认 true - showGrid: boolean - 是否显示网格,默认 false - showGridDot: boolean - 是否显示网格顶点,默认 false - color: { r, g, b, a } - 网格和顶点颜色,默认红色 #### Returns [`Texture`](Texture.md) 返回实例本身,支持链式调用 #### Example ```ts // 渲染设置 texture.setRenderOptions({ padding: 10, showTexture: true }); ``` #### Remarks 使用建议: 1. 生产环境建议保持 safe 为 true 2. padding 可用于预留变形溢出空间 *** ### setSplitStrategy() > **setSplitStrategy**(`strategy`): [`Texture`](Texture.md) 设置变形分割点的计算策略 自定义网格分割点的计算方法,通过不同的策略可以实现不同的变形效果。 #### Parameters ##### strategy `Strategy` 分割点计算策略对象 - name: 策略名称,用于标识不同的策略,自定义标识 - execute: 策略的执行函数,接收 texture 实例作为参数 #### Returns [`Texture`](Texture.md) 返回实例本身,支持链式调用 #### Example ```ts // 使用自定义策略 texture.setSplitStrategy({ name: 'custom', execute: (texture) => { // 返回自定义的网格点计算结果 return [[[{ x: 0, y: 0 }]]]; } }); ``` #### See Texture.strategy 查看默认策略的实现 *** ### setSplitUnit() > **setSplitUnit**(`splitUnit`): [`Texture`](Texture.md) 设置变形网格分割的最大比例 控制网格分割的精细程度。较小的值会产生更密集的网格, 从而实现更精细的变形效果,但同时也会增加计算量。 #### Parameters ##### splitUnit `number` 网格分割的最大比例值 - 范围:0-1 之间的数值 - 值为 0.1 时,单个网格最大为图像宽度的 10% - 值为 0.05 时,单个网格最大为图像宽度的 5% - 值大于 1 或小于等于 0 时会被重置为 1 #### Returns [`Texture`](Texture.md) 返回实例本身,支持链式调用 #### Example ```ts // 设置较密的网格以获得更精细的变形效果 texture.setSplitUnit(0.05); // 设置较疏的网格以提高性能 texture.setSplitUnit(0.2); ``` *** ### setTransformData() > **setTransformData**(`splitPoints`, `areaBound`): [`Texture`](Texture.md) 设置贴图的变形数据 使用指定的变形数据更新贴图的状态。可以用于: 1. 还原之前保存的变形状态 2. 在多个贴图之间复制变形效果 3. 使用预设的变形模板 #### Parameters ##### splitPoints `Coord`[] 分割点数组,每个点的坐标应该是相对于原始图像尺寸的比例值(0-1) ##### areaBound 边界曲线数据(可选) - 如果提供,将直接使用这些数据设置边界曲线 - 如果为 null,将根据分割点自动生成直线边界 `null` | `Record`\<`Direction`, `Coord`[]\>[][] #### Returns [`Texture`](Texture.md) 返回实例本身,支持链式调用 #### Example ```ts // 1. 使用完整的变形数据 const data = anotherTexture.getTransformData(); texture.setTransformData(data.splitRatioPoints, data.areaBound); // 2. 仅设置分割点,使用默认直线边界,将还原回无扭曲状态 texture.setTransformData([ { x: 0.5, y: 0.5 } // 在图像中心添加一个分割点 ]); ``` #### See - getTransformData 获取变形数据 - resetTransformData 重置变形状态 *** ### setVertexCoord() > **setVertexCoord**(`rowIndex`, `colIndex`, `vertexType`, `coord`, `redistribute`): [`Texture`](Texture.md) 更新单个变形后的贴图顶点的坐标 移动网格的某个顶点,并自动同步所有相关联的顶点以保持网格的连续性。 #### Parameters ##### rowIndex `number` 目标区域的行索引(从0开始) ##### colIndex `number` 目标区域的列索引(从0开始) ##### vertexType 要移动的顶点类型 - 'tl': 左上角顶点 - 'tr': 右上角顶点 - 'bl': 左下角顶点 - 'br': 右下角顶点 `"tl"` | `"tr"` | `"bl"` | `"br"` ##### coord `Coord` 顶点的新坐标 - x: X坐标(像素) - y: Y坐标(像素) ##### redistribute `boolean` = `true` 是否重新计算贝塞尔曲线控制点 - true: 重新计算以实现平滑过渡(默认) - false: 仅更新端点,保持曲线形状 #### Returns [`Texture`](Texture.md) 返回实例本身,支持链式调用 #### Example ```ts // 将区域(0,0)的左上角顶点移动到(100,100) texture.setVertexCoord( 0, // rowIndex 0, // colIndex 'tl', // vertexType { x: 100, y: 100 }, // 新位置 true // 重新计算曲线 ); ``` #### Remarks 注意事项: 1. 移动顶点会影响所有相连的顶点和曲线 2. 设置 redistribute=false 可以在移动时保持曲线形状 3. 无效的行列索引会被静默忽略 #### See _setSingleAreaVertexCoord 内部顶点更新方法 *** ### useCanvasRender() > **useCanvasRender**(): [`Texture`](Texture.md) 设置使用 Canvas 2D 进行渲染 将渲染引擎设置为 Canvas 2D 模式。这种模式具有以下特点: - 兼容性最好,支持所有现代浏览器 - 适合处理中小尺寸图像的变形 - 性能相对 WebGL 较低,但稳定性高 #### Returns [`Texture`](Texture.md) 返回实例本身,支持链式调用 #### Example ```ts // 创建实例并设置为 Canvas 2D 渲染 const texture = new Texture(image) .useCanvasRender() .create(); ``` #### See useWebGLRender 切换到 WebGL 渲染模式 *** ### useInstanceCanvas() > **useInstanceCanvas**(`canvas`): [`Texture`](Texture.md) 设置使用单例画布进行渲染 指定一个固定的画布用于渲染输出。这在以下场景特别有用: - 需要复用同一个画布进行多次渲染 - 需要直接操作输出画布的内容 #### Parameters ##### canvas 指定的画布元素 - 传入 null 或不传参数时会创建新的画布 `null` | `HTMLCanvasElement` #### Returns [`Texture`](Texture.md) 返回实例本身,支持链式调用 #### Example ```ts // 1. 使用已有画布 const canvas = document.createElement('canvas'); texture.useInstanceCanvas(canvas); // 2. 创建新画布 texture.useInstanceCanvas(); // 3. 在动画循环中复用画布 const canvas = document.createElement('canvas'); texture.useInstanceCanvas(canvas); function animate() { // 每帧都在同一个画布上更新内容 texture.create(); requestAnimationFrame(animate); } ``` #### Remarks 性能提示: - 在需要频繁更新的场景中,使用单例画布可以减少内存分配 - 避免在每次渲染时都创建新的画布实例 *** ### useWebGLRender() > **useWebGLRender**(): [`Texture`](Texture.md) 设置使用 WebGL 进行渲染 将渲染引擎设置为 WebGL 模式。这种模式具有以下特点: - 性能最佳,特别适合处理大尺寸图像 - 支持 GPU 加速,渲染速度快 - 内存占用相对较低 #### Returns [`Texture`](Texture.md) 返回实例本身,支持链式调用 #### Remarks 重要说明: 1. 当设置为 安全渲染模式 时,当浏览器不支持 WebGL或某些特殊情况下渲染失败时,会自动降级使用 Canvas 2D 2. 建议在处理大尺寸图像时优先使用此模式 #### Example ```ts // 创建实例并设置为 WebGL 渲染 const texture = new Texture(image) .useWebGLRender() .create(); ``` #### See useCanvasRender 切换到 Canvas 2D 渲染模式 *** ### compressTransformData() > `static` **compressTransformData**(`transformData`): `string` 压缩变形数据 将贴图的变形数据压缩为 base64 字符串格式,便于传输和存储。 压缩的数据包含: - 分割点信息(splitRatioPoints) - 区域边界变形信息(areaBound) #### Parameters ##### transformData `TransformData` 需要压缩的变形数据 包含分割点和边界变形信息的对象 #### Returns `string` 返回压缩后的 base64 字符串 #### Example ```ts // 1. 获取当前贴图的变形数据 const transformData = texture.getTransformData(); // 2. 压缩数据 const compressed = Texture.compressTransformData(transformData); ``` #### See - decompressTransformData 解压缩变形数据 - getTransformData 获取变形数据 *** ### decompressTransformData() > `static` **decompressTransformData**(`base64String`): `TransformData` 解压缩变形数据 将通过 compressTransformData 压缩的数据还原为可用的变形数据对象。 解压缩后可以直接用于重建贴图的变形状态。 #### Parameters ##### base64String `string` 通过 compressTransformData 压缩得到的 base64 字符串 #### Returns `TransformData` 解压缩后的变形数据对象 splitRatioPoints - 分割点数组,每个点包含相对坐标 (x,y) boundData - 边界变形数据,包含每个区域的边界信息 #### Example ```ts // 1. 解压缩数据 const { splitRatioPoints, boundData } = Texture.decompressTransformData(data); // 2. 应用变形数据 texture.setTransformData(splitRatioPoints, boundData); ``` #### See - compressTransformData 压缩变形数据 - setTransformData 应用变形数据 *** ### strategy() > `static` **strategy**(`texture`): `Coord`[][][] 内置扭曲分隔策略 这是一个默认的网格分割策略,通过计算横纵向贝塞尔曲线的交点中点来生成网格点。 该策略能够很好地表现出平面扭曲的效果,特别适合用于: - 图像弯曲变形 - 透视变形 - 波浪效果 #### Parameters ##### texture [`Texture`](Texture.md) 当前的贴图实例 #### Returns `Coord`[][][] 返回三维数组,包含所有分割区域的网格点坐标 - 第一维:区域行索引 - 第二维:区域列索引 - 第三维:该区域内的网格点列表 #### Example ```ts // 1. 使用默认策略 const texture = new Texture(image); // 默认已经使用此策略,无需额外设置 // 2. 显式设置此策略 texture.setSplitStrategy({ name: 'default', execute: Texture.strategy }); ``` #### Remarks 该策略的工作原理: 1. 遍历每个分割区域 2. 计算区域内横向和纵向贝塞尔曲线的交点 3. 取每对交点的中点作为网格点 4. 这样可以保证网格点均匀分布,且能跟随曲线变形