beginpath是canvas路径绘制的关键开关,用于清空旧路径并准备新图形;不调用会导致路径意外连接、填充错乱;复杂几何体需每个子图形严格遵循beginpath→定义顶点→fill/stroke三步结构。

Canvas路径绘制的核心在于用beginPath明确划分图形边界,而不是单纯堆砌绘图命令。它不是“开始画”,而是“清空旧路径、准备新图形”的关键开关。不调用beginPath,后续的moveTo、lineTo等操作会追加到上一条路径里,导致意外连接、填充错乱或描边粘连。
为什么beginPath是复杂几何体的前提
多个独立图形(比如一组齿轮齿、分层嵌套的多边形、带缺口的环形)必须各自拥有干净的路径上下文。否则:
- 两次fill()可能把本该分开的区域合并填充
- stroke()会把不同图形的边缘连成一条长线
- 使用clip()裁剪时,脏路径会导致裁剪区域错位
构建复杂几何体的三步结构
每个子图形都应严格遵循:beginPath → 定义顶点/曲线 → fill/stroke。例如绘制一个带内孔的六边形(类似垫片):
- 先ctx.beginPath(),用lineTo绕外六边形一圈,再ctx.closePath()
- 再ctx.beginPath(),用lineTo绕内六边形一圈(注意方向:内圈需逆向,确保fill自动识别为“挖空”)
- 最后只调用一次ctx.fill(),Canvas会按非零环绕规则自动处理内外区域
配合closePath与控制点提升精度
闭合路径不只是视觉收尾,更是填充逻辑的依据。对非凸或含曲线的几何体,closePath能避免因起点终点微小偏移造成的缝隙:
- 用bezierCurveTo绘制花瓣时,起点和终点坐标即使相同,也建议显式closePath,防止抗锯齿下出现白边
- 组合弧线(arc)和直线时,closePath会补一条直线——若不想要这条线,就改用stroke()后手动lineTo回起点,再fill()
- 心形、水滴、箭头等常见复杂体,通常由2–4段贝塞尔曲线拼接,每段前都应有独立的beginPath
用Path2D复用路径提升可维护性
当同一几何体需多次绘制(如网格中的重复单元、粒子系统里的图标),直接重复写路径代码易出错。Path2D对象可封装路径逻辑:
- const gearTooth = new Path2D(); gearTooth.moveTo(0,0); gearTooth.lineTo(10,-5); ……
- 后续用ctx.stroke(gearTooth)或ctx.fill(gearTooth)即可,无需重复beginPath
- 还能用ctx.addPath()叠加多个Path2D,实现模块化组装











