如何通过Path2D在HTML Canvas指定位置绘制SVG路径?
问题描述
现有如下绘制心形的代码:
const ctx = document.querySelector("canvas").getContext("2d"); const pathHeart = new Path2D("M9.293 1.55l.707.708.707-.707a5 5 0 1 1 7.071 7.071l-7.07 7.071a1 1 0 0 1-1.415 0L2.222 8.622a5 5 0 1 1 7.07-7.071z"); ctx.fill(pathHeart);
<canvas></canvas>
需求是将心形绘制在指定位置(比如画布的(x:100, y:100)处),希望实现类似ctx.fill(pathHeart, 100, 100)的效果。由于应用状态不同,图标绘制位置会变化,无法直接编辑路径数据。
曾考虑过平移整个画布后绘制再复原,但觉得该方式繁琐且可能影响性能,想知道是否有更优方案。另外,Safari不支持用context.drawImage绘制SVG,该方式无法使用。
解决方案
方法1:使用Path2D变换(推荐)
Path2D本身支持通过addPath结合变换矩阵平移路径,无需修改原始路径,也不用操作画布状态:
const ctx = document.querySelector("canvas").getContext("2d"); const pathHeart = new Path2D("M9.293 1.55l.707.708.707-.707a5 5 0 1 1 7.071 7.071l-7.07 7.071a1 1 0 0 1-1.415 0L2.222 8.622a5 5 0 1 1 7.07-7.071z"); // 创建x偏移100、y偏移100的变换矩阵 const translateMatrix = new DOMMatrix([1, 0, 0, 1, 100, 100]); // 基于原始路径生成平移后的新路径 const translatedPath = new Path2D(); translatedPath.addPath(pathHeart, translateMatrix); // 绘制平移后的路径 ctx.fill(translatedPath);
优势:
- 原始路径可复用在其他位置,无需重复定义
- 不操作画布全局状态,避免状态污染
- 性能开销极低,仅创建新Path2D对象和变换矩阵
方法2:优化版画布平移(性能无影响)
画布平移的实际操作并不繁琐,现代浏览器对状态栈的操作性能可以忽略,是开发中常用的方案:
const ctx = document.querySelector("canvas").getContext("2d"); const pathHeart = new Path2D("M9.293 1.55l.707.708.707-.707a5 5 0 1 1 7.071 7.071l-7.07 7.071a1 1 0 0 1-1.415 0L2.222 8.622a5 5 0 1 1 7.07-7.071z"); // 保存当前画布状态 ctx.save(); // 将画布原点平移到目标位置 ctx.translate(100, 100); // 绘制路径 ctx.fill(pathHeart); // 恢复画布原始状态 ctx.restore();
方法3:封装成工具函数
如果需要频繁在不同位置绘制,可封装函数实现类似ctx.fill(path, x, y)的调用方式:
function fillPathAt(ctx, path, x, y) { const translateMatrix = new DOMMatrix([1, 0, 0, 1, x, y]); const translatedPath = new Path2D(); translatedPath.addPath(path, translateMatrix); ctx.fill(translatedPath); } // 调用示例 fillPathAt(ctx, pathHeart, 100, 100); fillPathAt(ctx, pathHeart, 200, 200); // 复用原始路径绘制在另一位置
内容的提问来源于stack exchange,提问作者Ryan Peschel
相关产品推荐
相关产品推荐

