canvas无图层概念,层级由绘制顺序决定:先画在下、后画在上;需用save/restore隔离样式状态;globalcompositeoperation须提前设置;多图层场景宜分canvas叠放或建图层栈管理。

Canvas 本身没有图层概念,图形与文字的“层次叠加”完全靠绘制顺序决定:先画的在下,后画的在上。控制好这个顺序,就能精准实现遮挡、高亮、蒙版、UI浮层等效果。
绘制顺序就是层级顺序
Canvas 是立即模式绘图,所有内容按代码执行顺序逐帧写入像素。没有“z-index”,只有“谁先画、谁后画”。比如:
- 先 drawImage 背景图 → 它在最底层
- 再 fillText 写标题 → 文字盖在背景上
- 最后 strokeRect 画边框 → 边框又盖在文字上
反过来写,边框就可能被文字遮住。顺序错了,视觉逻辑就乱了。
用 save/restore 隔离状态,避免样式污染
文字和图形常需不同字体、颜色、透明度。如果直接连续调用 ctx.fillStyle 或 ctx.globalAlpha,容易互相影响。推荐每块内容单独封装,并配合 save/restore:
- ctx.save() 保存当前所有绘图状态(坐标变换、alpha、lineWidth 等)
- 设置该图层/元素所需的样式,绘制图形或文字
- ctx.restore() 恢复到上一次 save 的状态,不影响后续绘制
这样文字不会意外继承图片的 globalAlpha,也不会因 rotate() 导致后续文字歪斜。
混合模式要提前设,且只对后续操作生效
globalCompositeOperation 控制的是“新画上去的内容”和“已有像素”之间的像素运算关系。它不是颜色混合,而是裁剪+覆盖逻辑:
- 想让文字作为蒙版抠出图片,得先画图片(destination),再设 ctx.globalCompositeOperation = 'destination-in',最后画文字(source)
- 想让高亮色仅出现在图片非透明区域,用 'source-in':先画图片,再设模式,再画高亮矩形
- 切记:模式必须在 drawImage / fillText 前设置;设晚了,对已画内容无效
多图层场景建议分 canvas 或建图层栈
如果图形、文字、动画更新频率不同(比如背景静止,文字实时变化),硬挤在一个 canvas 里频繁重绘效率低。更稳妥的做法是:
- 用多个同尺寸 canvas 叠放:背景 canvas(z-index: 1)、文字 canvas(z-index: 2)、特效 canvas(z-index: 3)
- 每个 canvas 独立清空与重绘,互不干扰;文字 canvas 可设 pointer-events: none,保证点击穿透到底层
- 或者单 canvas 内维护图层配置对象,按 visible、priority、opacity 字段控制遍历顺序和绘制参数











