Canvas实时多图曝光核心是像素级合成:预加载图片并设crossOrigin,用Promise.all统一等待;按顺序设置globalCompositeOperation(如lighten/multiply/overlay)逐帧混合;固定画布尺寸、避免clearRect、用requestAnimationFrame驱动;每图对象含opacity/blendMode,支持动态调整与toDataURL导出。

用 Canvas 实现网页端实时多图曝光,核心是控制像素级合成——不是简单堆叠图片,而是通过 globalCompositeOperation 和精确的绘制时序,在单个画布上逐帧混合图像数据。关键不在“多张图同时显示”,而在“每张图参与最终像素值计算”。
必须预加载并确保图像就绪
实时曝光依赖连续、无空白帧的绘制,任何一张图未加载完成都会导致合成中断或黑块。
- 每张
<img>创建后立即设img.crossOrigin = 'anonymous'(尤其 CDN 图片),否则后续getImageData或导出会报错 - 用
Promise.all(图片数组.map(img => new Promise(...)))统一等待全部 onload,拒绝失败项便于定位问题源 - 不依赖
img.complete轮询或setTimeout,这些在高帧率下不可靠
按曝光逻辑选对合成模式
不同曝光效果对应不同 globalCompositeOperation 值,且必须在绘制第二张及之后的图前设置,否则无效。
-
正向双重曝光(亮部叠加):第一张正常绘制 → 设
ctx.globalCompositeOperation = 'lighten'→ 绘第二张。适合人像+光斑、星空叠加 -
反向双重曝光(暗部强化):第一张正常绘制 → 设
ctx.globalCompositeOperation = 'multiply'→ 绘第二张。适合纹理底图+人像阴影融合 -
柔光叠加(中间调增强):用
'overlay',但注意 Safari 对部分模式支持滞后,iOS 15.4+ 才稳定支持'lighten'
保持帧率稳定与像素精度
实时意味着每秒多次重绘,需避免清空全画布、重复设尺寸等重开销操作。
- Canvas 尺寸只初始化一次(如
canvas.width = targetWidth; canvas.height = targetHeight),后续绝不重赋值,否则上下文被清空 - 不用
clearRect(0,0,w,h)全屏擦除,改用drawImage覆盖旧内容,或仅清除变化区域 - 所有图像统一缩放到目标画布尺寸再绘制,避免 drawImage 内部插值模糊;若需保留原始分辨率,用 CSS 缩放 canvas 元素,而非改
width/height属性 - 启用
requestAnimationFrame驱动循环,比setInterval更贴合屏幕刷新节奏
支持动态调整与导出
真实场景中用户可能要调透明度、换图、保存结果,这些需在合成链路中留出接口。
- 每张图对应一个对象,含
image、opacity、blendMode字段,渲染时按顺序遍历,用ctx.globalAlpha控单图透明度,ctx.globalCompositeOperation控混合方式 - 导出为 PNG 或 JPEG 时直接调
canvas.toDataURL('image/png'),无需额外 canvas 中转 - 如需叠加滤镜(如高斯模糊后再曝光),可在绘制某图后调
ctx.filter = 'blur(2px)',但注意 filter 是上下文状态,需及时重置
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











