最直接方案是用 CSS transform:水平翻转用 scaleX(-1),垂直用 scaleY(-1),180°翻转用 scale(-1,-1);Canvas 绘制需先 translate 再 scale 以避免越界;MediaStream 视频默认镜像显示,仅需 CSS 控制即可。

用 CSS transform 实现 HTML5 元素镜像翻转最直接
HTML5 本身没有内置“滤镜”API 支持镜像翻转,所谓“HTML5 滤镜”通常指在 中手动操作像素,或更常用、更轻量的方案:用 CSS 的 transform 对视频、图片、Canvas 元素做视觉翻转。浏览器原生支持,无性能损耗,且兼容性好(Chrome 12+、Firefox 3.5+、Safari 4+、Edge 12+)。
关键点是:镜像不是“滤镜”,而是坐标系变换。水平翻转 = X 轴缩放 -1;垂直翻转 = Y 轴缩放 -1。
-
transform: scaleX(-1):水平镜像(左右翻转),适合自拍类视频预览 -
transform: scaleY(-1):垂直镜像(上下翻转),较少用,但可用于倒影效果 -
transform: scale(-1, -1):中心点 180° 翻转(等效于旋转 180°) - 注意:翻转后文字也会反向,若需保持文字正常,应单独对子元素设置
scaleX(-1)补正
Canvas 绘制时翻转 video 或 image 的正确顺序
在 中绘制镜像内容,不能只靠 CSS —— 因为 canvas 画布本身是位图,CSS 翻转只是最终渲染层变形,若后续要截图(toDataURL)、上传或做图像处理,必须在绘图时就翻转像素坐标。
核心原则:先 ctx.scale(-1, 1),再调整绘制原点,否则图像会画到画布外。
立即学习“前端免费学习笔记(深入)”;
- 水平镜像 video:
ctx.translate(canvas.width, 0); ctx.scale(-1, 1); ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
- 垂直镜像:
ctx.translate(0, canvas.height); ctx.scale(1, -1); ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
- 必须在
drawImage前调用translate+scale,否则图像被缩放后偏移出界 - 翻转后若需叠加文字或图形,记得在绘制前恢复坐标系:
ctx.setTransform(1, 0, 0, 1, 0, 0)
MediaStream 视频流翻转(如 getUserMedia 摄像头)
前端调用摄像头时,getUserMedia 返回的 MediaStream 默认是“镜像模式”(即用户看到的是自己照镜子的效果),但实际流数据仍是原始方向。很多开发者误以为需要 JS 处理翻转,其实只需 CSS 控制显示即可,且更高效。
- 让
标签显示镜像(自拍感):video { transform: scaleX(-1); transform-origin: center; } - 若需保存/上传镜像帧,仍要在 canvas 绘制时按上一节方式翻转(因为流本身未变)
- 不建议用
mirror: true这类不存在的属性——HTML 规范中无此配置项 - 某些安卓 WebView 对
scaleX(-1)渲染有闪烁,可加will-change: transform缓解
filter: url(#svg-filter) 不适合做镜像翻转
有人尝试用 SVG + 或 实现翻转,这是典型误区。SVG filter 是像素级颜色处理,不改变几何坐标,无法实现真正的镜像(它连宽高都不影响)。强行用 + 坐标偏移模拟,代码复杂、性能差、兼容性极差(尤其 Safari)。
真正需要像素级控制(比如翻转同时加灰度、模糊)的场景,应组合使用:transform 控制几何 + filter 控制色彩,而不是试图用 filter 做 transform 的事。
镜像翻转本质是仿射变换,浏览器早已通过 transform 和 canvas 2D context 提供了稳定、标准、高性能的路径。绕开它们去折腾 SVG filter 或 WebGL,往往是为复杂而复杂。










