capture属性在混合app中不触发权限请求,仅是提示;微信/钉钉/uni-app webview因内核不支持而忽略该非标准属性;需https、用户手势、精确accept三者齐全才可能生效;推荐用getusermedia或uni.chooseimage替代。

capture 属性在混合 App 中根本不会“触发权限请求”,它只是个提示,浏览器或 WebView 会根据上下文静默决定用相机还是图库——你看到没反应、弹相册、或控制台无报错,都是正常降级,不是 bug。
为什么 capture 在微信/钉钉/uni-app WebView 里完全不生效
因为绝大多数第三方 WebView(包括微信内置浏览器、钉钉、部分安卓厂商定制 WebView)压根不解析 capture 属性。它不是标准 HTML 属性,而是 WebKit/Blink 的非规范扩展,而这些 WebView 基于旧版 Chromium 或自研内核,直接忽略该字段。
- 检查 UA:
navigator.userAgent包含MicroMessenger或DingTalk时,capture基本无效 - uni-app 的
web-view组件默认走系统 WebView,iOS 上可能 fallback 到 SafariView,Android 上大概率是低版本 X5 内核 - 即使写了
accept="image/*" capture,也会被降级为普通文件选择器,且不会抛任何错误
HTTPS + 用户手势 + accept 精确值,三者缺一不可
哪怕在 Chrome for Android 上,capture 也只在严格满足以下条件时才可能生效:
- 页面必须通过
https://访问(HTTP 下 iOS Safari 和 Chrome 84+ 直接禁用媒体设备访问) - 触发
input.click()必须发生在用户真实点击/触摸事件回调中,不能在setTimeout、Promise.then或mounted钩子中调用 -
accept必须显式写成accept="image/*"或更精确如accept="image/jpeg,image/png";accept=""或accept="*"会被忽略 - 不能带
multiple—— 多数系统遇到multiple会直接禁用capture
capture="user" 和 capture="environment" 的实际支持度极低
这两个值在规范中存在,但实际兼容性非常差:
- iOS Safari 只认
capture(无值)或capture="user",capture="environment"被完全忽略(即使 iOS 16.4+) - Android Chrome 84+ 开始要求写成
accept="image/*;capture=camera"才识别,原生capture="environment"不起作用 - 第三方 WebView(如 QQ 浏览器、华为浏览器)基本不支持任何
capture值,只响应accept - 建议直接省略
capture值,只保留accept="image/*",靠浏览器自动匹配最可能的采集方式
真正可控的方案:用 getUserMedia + canvas 手动拍照
如果业务需要确定调起摄像头、实时预览、多帧拍摄或自定义 UI,capture 属性已不可靠,必须切换到 MediaDevices.getUserMedia:
- 需先申请权限:
navigator.mediaDevices.getUserMedia({ video: true }),失败时明确抛出NotAllowedError或NotFoundError - 拿到流后绑定到
<video></video>元素,用canvas.captureStream()或canvas.getContext('2d').drawImage()截帧 - 注意 Android 某些 ROM(如 MIUI、EMUI)会把摄像头权限藏在「应用管理→浏览器→权限管理」里,需引导用户手动开启
- uni-app 中可用
uni.chooseImage({ sourceType: ['camera'] })替代,这是原生层封装,比 Web API 更稳定
真正麻烦的从来不是怎么写 capture,而是判断当前运行环境是否支持它——而这个判断本身就需要先尝试 getUserMedia 或检测 UA,再 fallback。别指望一个属性解决所有问题。











