Canvas fill()支持nonzero和evenodd两种填充规则:nonzero依据绕数是否为零判断填充,evenodd仅看射线交点数奇偶;两者均依赖路径绘制方向,通过fill('nonzero')或fill('evenodd')切换。

Canvas 中的 fill() 方法支持两种填充规则:nonzero(非零环绕)和 evenodd(奇偶)——它们决定当路径自我交叉或嵌套时,哪些区域被实际填充。关键不在“画了什么”,而在“怎么绕”。
理解绕行方向是核心
两种规则都依赖路径各段的绘制方向(顺时针或逆时针)。Canvas 不自动判断形状朝向,而是忠实记录你调用 lineTo()、arc()、rect() 等时的坐标顺序。
- 顺时针闭合路径 → 绕数 +1
- 逆时针闭合路径 → 绕数 −1
- 多子路径独立计算绕数,再累加
Nonzero 规则:看绕数是否为零
对画布上任一像素点,从该点向任意方向(如向右)引一条射线,统计它与所有路径段的交点处的绕数变化总和。若总和 ≠ 0,则填充该点。
- 单个顺时针矩形:所有内部点绕数 = +1 → 填充
- 外顺时针圆 + 内逆时针圆(同心环):环内区域绕数 = +1 + (−1) = 0 → 不填充(形成空心)
- 两个重叠的顺时针三角形:重叠区绕数 = +1 + +1 = +2 ≠ 0 → 填充(无镂空)
Evenodd 规则:只看交点个数奇偶性
同样从像素点向右引射线,只统计它与路径的交点总数(不区分方向)。若交点数为奇数,则填充;偶数则不填充。
- 单个闭合路径(无论顺/逆时针):内部交点恒为 1(奇)→ 全部填充
- 外矩形顺时针 + 内矩形逆时针:重叠区交点数 = 2(偶)→ 不填充(自动抠空)
- 五角星(单路径,自交):尖角处交点数为 1,凹陷处为 3,但所有内部点交点数均为奇 → 整体实心填充
在代码中切换规则
通过 fill() 或 fillText() 的第二个参数指定:
-
ctx.fill('nonzero')—— 默认值,可省略 -
ctx.fill('evenodd')—— 显式启用奇偶规则 - 注意:
clip()也支持相同参数,影响后续绘制的裁剪区域
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











