问题
开发一个微信小程序项目的时候需要用到Path2D这个对象,但是发现小程序的Path2D对象不支持实例化的时候直接传入’svg path’,导致下面的代码运行的时候报错(浏览器中可运行)
1 2 3 4 5 6
| #其它代码(省略) ...
let p = new Path2D("M10 10 h 80 v 80 h -80 Z"); ctx.fill(p);
|
而小程序的Path2D对象只支持用命令式编程的方式去构建Path2D路径,代码如下:
1 2 3 4 5 6 7 8 9 10 11
| #其它代码(省略) ...
let p = new Path2D(); p.moveTo(10, 10); p.lineTo(90, 10); p.lineTo(90, 90); p.lineTo(10, 90); p.closePath(); ctx.fill(p);
|
这种方式有两个问题:
- 路径比较复杂这样的绘制代码就会很多(不优雅)
- 不能使用现有svg path(主要问题)
解决办法
查了相关的开发文档之后决定写一个工具函数svgPathStringToCanvas
来解析svg path
并且生成这样的绘制命令,这样就完美解决了上面两个问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| function svgPathStringToCanvas(svgPathData) { console.log(svgPathData); const pathParts = svgPathData .split(/(^|\s+)(?=[A-Z])/) .filter((part) => part !== " "); const canvasCommands = []; for (const part of pathParts) { const [cmd, ...rawParams] = part.split(/\s+/); const params = rawParams.map((param) => parseFloat(param)); if (cmd === "M") { canvasCommands.push((ctx) => ctx.moveTo(...params)); } else if (cmd === "L") { canvasCommands.push((ctx) => ctx.lineTo(...params)); } else if (cmd === "C") { canvasCommands.push((ctx) => ctx.bezierCurveTo(...params)); } else if (cmd === "Q") { canvasCommands.push((ctx) => ctx.quadraticCurveTo(...params)); } else if (cmd === "Z") { canvasCommands.push((ctx) => ctx.closePath()); } } return (ctx) => canvasCommands.forEach((cmd) => cmd(ctx)); }
|
有了这个函数就可以不使用Path2D相关api了,兼容性也更好了。
使用方式
1 2 3 4 5 6 7
| #其它代码(省略) ...
var canvasPathFun = svgPathStringToCanvas("M10 10 h 80 v 80 h -80 Z"); canvasPathFun(ctx) ctx.fill()
|
参考文档