遮罩层不能用 position: fixed,需按平台差异化处理:app 端挂载到 page 根外层,h5 端用 absolute + 100vh/vw + translatez(0);cover-view 须用于扫描框且禁用 flex/嵌套;事件需 catchtouchmove + catchtap 双拦截。

不能直接用 position: fixed 套在普通 view 上,否则 H5 端 iOS 会错位、App 端会被 scroll-view 切掉。
为什么遮罩层会“跟着滚动”或“消失”
本质是 WebView 渲染机制差异:iOS Safari 和部分安卓 WebView 对 position: fixed 支持不一致;scroll-view 创建了新层叠上下文和裁剪区域,内部的 fixed 元素会被截断。uni-app 的 uni.showModal 等原生弹窗不暴露 DOM,无法覆盖其样式,所以必须手写遮罩,但写法不对就失效。
常见错误现象包括:
- 点开扫码页后下拉页面,遮罩层跟着动(不是固定在视口)
- 扫码框只显示一半,或四个角被切掉(
scroll-view的overflow: hidden导致) - H5 端在微信内置浏览器里遮罩完全不出现(
pointer-events: none失效 + 事件穿透)
正确挂载位置与定位方式
遮罩层必须脱离页面常规流,避免受父容器 transform、overflow 或 scroll-view 影响。核心是“挂得高、定位准、硬件加速稳”。
- App 端(iOS/Android):遮罩和扫描框需挂载到
page根节点外层,推荐用uni.createSelectorQuery().in(uni.getTopLevelPage())获取顶层容器,再append遮罩节点 - H5 端:改用
position: absolute; top: 0; left: 0; width: 100vw; height: 100vh;,并加transform: translateZ(0)强制硬件加速,防闪烁 - 所有平台:遮罩层
z-index至少设为9999,扫描框内容(如cover-view)设为10000,且确保其父容器没设overflow: hidden或transform
cover-view 与 cover-image 的边界约束
cover-view 是唯一能在 camera 组件上层渲染的视图容器,但它有硬性限制:不能嵌套普通 view,不能使用 Flex 布局,动画必须用 animation 属性而非 CSS transition;cover-image 只支持网络地址或本地 /static 路径,不支持动态 base64。
- 扫描框四角用
cover-view拼成,不要试图用一个cover-image覆盖全屏再挖空——cover-image不支持clip-path - 扫描线动画必须用
cover-view+animation实现,例如:animation: scanLineMove 2s infinite;,不能用transform: translateY()配合transition - 文字提示(如“将二维码放入框内”)必须用
cover-view包裹cover-text,普通text组件在camera上不可见
事件穿透与点击拦截要点
遮罩层点不关闭、扫完码还能点到后面按钮,根本原因是 touch 事件未完全捕获。uni-app 的事件冒泡控制比小程序更弱,尤其在 H5 微信环境。
- 遮罩层必须同时写
catchtouchmove和catchtap,只写catchtap在 iOS 快速点击时仍可能穿透 - 扫描框内部(如
cover-view)也要加catchtouchmove,否则 Android 微信里手指划过扫描框会触发背景滚动 - 禁止依赖
pointer-events: none控制交互——H5 端兼容性差,App 端部分系统版本不识别 - 如果用了
plus.barcode.create原生扫码,遮罩层只是视觉层,实际扫码区域由原生容器决定,务必保证scanNativeContainer的宽高与遮罩框严格对齐,否则识别范围错位
最易被忽略的是:App 端若页面启用了下拉刷新(enablePullDownRefresh: true),遮罩层必须在 onPullDownRefresh 触发前手动隐藏,否则下拉时遮罩会被强制重绘导致闪退;H5 端若用 uni.scanCode 回退再进扫码页,需手动清理上次创建的 cover-view 节点,否则内存泄漏叠加导致卡顿。











