canvas无内置图层,需用javascript模拟:为每层创建独立离屏canvas,数组管理顺序与属性,主画布仅合成渲染;交互需坐标映射与命中检测;性能靠脏矩形、操作指令快照及dpi适配。

Canvas 本身没有内置图层概念,所谓“多图层”完全靠开发者用 JavaScript 模拟实现。核心思路是:把每个图层抽象为独立的 Canvas 实例(或数据结构),按绘制顺序叠加渲染,并统一管理其可见性、透明度、混合模式和变换状态。
图层容器:用数组管理独立 Canvas 实例
不复用单个 <canvas></canvas>,而是为每个图层创建一个离屏 Canvas(document.createElement('canvas')),保存其宽高、内容、属性(如 visible、opacity、blendMode、transform)。所有图层按从底到顶顺序存入数组:
例如:layers = [backgroundLayer, photoLayer, textLayer, overlayLayer]
- 每个图层 Canvas 独立绘制,互不干扰——擦除、重绘、撤销只影响本层
- 主画布仅作最终合成输出,每次渲染时清空并按序 drawImage 所有可见图层
- 支持动态增删图层:push / splice,再触发一次完整重绘即可
合成渲染:按序 drawImage + 全局 compositeOperation
主画布的渲染函数类似 Photoshop 的“拼合图层”:
- 先
ctx.clearRect(0, 0, canvas.width, canvas.height) - 遍历
layers,跳过visible === false的图层 - 对每个图层设置
ctx.globalAlpha = layer.opacity和ctx.globalCompositeOperation = layer.blendMode(如'multiply'、'screen') - 调用
ctx.drawImage(layer.canvas, x, y, width, height)—— 若需缩放/旋转,可先用ctx.save()+ctx.transform()或直接在图层 Canvas 内部预变换
交互与编辑:坐标映射 + 图层命中检测
鼠标事件(如拖动、选区、画笔)需转换到当前编辑图层的局部坐标系:
- 监听主画布的
mousemove,用getBoundingClientRect()计算相对于主画布的 clientX/Y - 减去图层自身的偏移(如 position: absolute 的 left/top)、再除以缩放比例,得到该图层 Canvas 内部坐标
- 若启用“图层锁定”或“仅编辑当前图层”,操作前先检查
activeLayer === layer,再在其对应 Canvas 上执行 2D 绘图命令(beginPath、lineTo等) - 选区工具(矩形/套索)结果可存为路径对象或蒙版 Canvas,绑定到指定图层,后续裁剪/填充均作用于该图层像素
状态与性能:快照 + 脏矩形 + 分辨率适配
真实编辑场景需兼顾响应与内存:
- 每层维护
lastRenderTime和dirtyRect(如{x, y, width, height}),仅重绘变化区域,避免全层重绘 - 历史记录(Undo/Redo)不存像素,而存操作指令(如
{type:'drawLine', layerId:2, points:[...], color:'#f00'}),回放时重绘该图层 - 高 DPI 屏幕下,图层 Canvas 的
width/height设为实际CSS宽高 × window.devicePixelRatio,绘制时用ctx.scale(ratio, ratio)保持清晰 - 隐藏图层仍保留在内存中(非销毁),切换可见性只需跳过 drawImage 步骤,保证快速显示
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











