关键在于定义逻辑闭合路径:先beginPath()清空状态,再moveTo设起点,接着lineTo按序连接顶点,最后closePath自动闭合,fill()/stroke()渲染;动态顶点数组可提升灵活性与可维护性。

用 Canvas 的 moveTo 和 lineTo 构建复杂多边形,关键不是“连几条线”,而是“定义一个逻辑闭合的路径”。只要顶点坐标明确、顺序合理、状态管理得当,三角形、星形、不规则轮廓甚至带缺口的形状都能准确呈现。
正确启动路径并设定起点
moveTo(x, y) 不画线,只把“虚拟笔尖”移到指定位置——这是整个多边形的起始锚点。它必须紧跟在 beginPath() 之后,否则可能从上一次路径终点开始连线,造成意外粘连。
- 每次绘制新图形前,务必先调
ctx.beginPath(),清空旧路径状态 - 第一个操作几乎总是
ctx.moveTo(x0, y0),对应多边形第一个顶点 - 不要省略这一步;直接
lineTo会延续上一路径终点,极易出错
按序连接顶点,避免手动回连
用 lineTo(x, y) 依次连接后续所有顶点。注意:最后一个顶点连完后,不要再写一次 lineTo(x0, y0) 回到起点——这是常见冗余操作,会导致描边加粗或填充异常。
- 假设有顶点数组
[[x0,y0], [x1,y1], [x2,y2], [x3,y3]],只需循环调用三次lineTo - 让
closePath()自动完成首尾闭合,它会从当前点画线回到moveTo的初始坐标,并重置当前点 - 手动回连 +
closePath()会多画一条重复线段,尤其在描边较宽时明显可见
闭合路径与渲染时机要匹配
closePath() 只负责闭合路径,本身不显示任何内容。真正让图形出现的是 fill() 或 stroke(),而且它们只作用于“当前未被干扰的路径”。
立即学习“前端免费学习笔记(深入)”;
-
fill()有自动闭合行为,即使漏掉closePath()也能填满;但stroke()不会,缺了就少一条边 -
closePath()后若又调moveTo()或lineTo(),路径被延长,闭合效果即失效 - 推荐固定顺序:
beginPath → moveTo → lineTo × N → closePath → fill()/stroke()
动态生成多边形的实用写法
把顶点存成数组,用代码生成路径,比手写一堆 lineTo 更可靠、易维护、适配任意边数。
示例:绘制五边形轮廓
const points = [[100,50], [150,30], [190,70], [170,120], [120,120]];
ctx.beginPath();
ctx.moveTo(points[0][0], points[0][1]);
for (let i = 1; i < points.length; i++) {
ctx.lineTo(points[i][0], points[i][1]);
}
ctx.closePath(); // 自动连回 [100,50]
ctx.stroke();



















