如何在Canvas中复用自定义SVG pattern实现图形填充
Canvas 自定义 Pattern 实现方案
Canvas 的createPattern()方法并非仅支持传入图片作为填充源,它支持传入任意CanvasImageSource类型,包括<img>元素、离屏 Canvas、<svg>元素、视频元素等,完全可以复现和 SVG 中完全一致的自定义 pattern 填充效果,两种常用实现路径如下:
方案1:直接复用现有 SVG 代码(零逻辑重写)
不需要重写 pattern 的绘制逻辑,直接把已有的 SVG 片段封装为合法的 SVG 文件,加载后作为 pattern 源即可:
- 补全 SVG 根节点声明,将已写好的 defs 和 pattern 放入节点内,注意给 SVG 根节点加上标准命名空间
- 将 SVG 字符串转为 Blob URL,通过 Image 对象加载
- 加载完成后传入
createPattern(),设置重复模式为repeat就能得到和 SVG 完全一致的填充效果
对应实现代码:
// 直接复用已有的SVG pattern代码 const svgString = ` <svg xmlns="http://www.w3.org/2000/svg" width="0" height="0"> <defs> <pattern id="hash4_4" width="8" height="8" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"> <rect width="4" height="8" transform="translate(0,0)" fill="lightgray"></rect> </pattern> </defs> <rect width="100%" height="100%" fill="url(#hash4_4)"></rect> </svg> `; // 转换为可被Image加载的URL const blob = new Blob([svgString], {type: 'image/svg+xml'}); const url = URL.createObjectURL(blob); const img = new Image(); img.onload = () => { const canvas = document.getElementById('target-canvas'); const ctx = canvas.getContext('2d'); // 生成填充pattern const fillPattern = ctx.createPattern(img, 'repeat'); ctx.fillStyle = fillPattern; // 正常绘制图形即可得到同款填充效果 ctx.fillRect(0, 0, 300, 300); // 加载完成后释放URL对象避免内存泄漏 URL.revokeObjectURL(url); }; img.src = url;
方案2:离屏 Canvas 绘制图案单元(性能更优)
如果不想依赖 SVG 解析,也可以直接在离屏 Canvas 上手动绘制 pattern 的最小重复单元,再把离屏 Canvas 作为createPattern的输入,这种方式渲染开销更低,适合动画、高频重绘的场景:
// 创建和pattern单元尺寸一致的离屏canvas const patternCanvas = document.createElement('canvas'); patternCanvas.width = 8; patternCanvas.height = 8; const pctx = patternCanvas.getContext('2d'); // 绘制和原SVG效果一致的45度斜纹单元 pctx.fillStyle = 'lightgray'; pctx.translate(4, 0); pctx.rotate(Math.PI / 4); pctx.fillRect(-4, -4, 4, 16); // 主canvas直接引用离屏canvas生成填充 const canvas = document.getElementById('target-canvas'); const ctx = canvas.getContext('2d'); const fillPattern = ctx.createPattern(patternCanvas, 'repeat'); ctx.fillStyle = fillPattern; ctx.fillRect(0, 0, 300, 300);
注意:如果需要调整 pattern 的缩放、偏移、旋转效果,不需要修改 pattern 源本身,直接在主 Canvas 绘图时通过
ctx.setTransform()调整坐标系即可,逻辑和 SVG 中patternTransform属性一致。
内容的提问来源于stack exchange,提问作者Kamil P.
相关产品推荐
相关产品推荐

