Canvas像素拷贝实现镜像翻转需手动重排ImageData的RGBA数组:水平镜像逐行对调列索引,垂直镜像交换行索引;复用ImageData、避免全量拷贝、结合requestAnimationFrame可保障实时性;注意跨域、索引公式、坐标映射等细节。

用 Canvas 像素拷贝技术实现网页端实时图像镜像翻转,核心在于手动操作 ImageData 的像素数组,按镜像逻辑重排 RGBA 数据,再写回画布。这种方式不依赖坐标变换,能精确控制每个像素,适合需要导出、滤镜叠加或避免视觉错位的场景。
水平镜像:左右像素逐行对调
水平翻转即每行像素从左到右变为从右到左。关键是对每一行,将第 j 列像素复制到新数据的第 (w−j−1) 列位置:
- 获取原始图像数据:
const src = ctx.getImageData(0, 0, w, h) - 创建目标 ImageData:
const dst = ctx.createImageData(w, h) - 遍历每行(i 从 0 到 h−1),每列(j 从 0 到 w−1):
dst.data[i*w*4 + j*4 + k] = src.data[i*w*4 + (w-j-1)*4 + k](k=0,1,2,3 对应 R/G/B/A) - 用
ctx.putImageData(dst, 0, 0)渲染结果
垂直镜像:上下行顺序整体翻转
垂直翻转即第 i 行变为第 (h−i−1) 行。只需调整行索引,列内像素顺序不变:
- 同样创建 dst ImageData
- 遍历每行 i:
dst.data[i*w*4 + j*4 + k] = src.data[(h-i-1)*w*4 + j*4 + k] - 注意:该方式不改变单行内像素顺序,只交换行位置
实时性保障:避免重复创建与同步阻塞
频繁调用 getImageData / putImageData 易引发性能瓶颈。优化要点:
- 复用 ImageData 实例:提前调用
createImageData(w, h)创建一次 dst,后续直接重用 - 跳过全量拷贝:若仅需镜像显示(无需保留原图),可省略 src 获取,直接在 dst 中按镜像索引写入——减少内存读取压力
- 配合 requestAnimationFrame:在动画循环中执行,确保与屏幕刷新率同步,避免卡顿
- 限制分辨率:对高清图先缩放至合适尺寸再处理,像素量减半,耗时可降为约 1/4
注意事项与边界处理
像素级操作看似底层,但几个细节极易出错:
- 跨域图片会触发安全异常:确保 img.crossOrigin = 'anonymous',且服务端返回 CORS 头
- ImageData 是一维数组:索引公式为
row × width × 4 + col × 4 + channel,channel=0(R),1(G),2(B),3(A) - 不支持透明度以外的合成模式:该方法只复制像素值,不会应用 globalAlpha 或 globalCompositeOperation
- 无法直接响应鼠标事件坐标:镜像后视觉位置变化,但 canvas 原始事件坐标未变,需手动映射(如水平镜像时 x' = width − x)
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











