capture属性已废弃,Chrome 96+彻底禁用,Safari仅旧版本支持;应改用MediaDevices.getUserMedia()调起摄像头,配合video预览和canvas截帧实现可控拍照上传。

capture属性在input中已废弃,别再用了
直接说结论:capture 属性在现代 HTML 标准中已被移除,Chrome 从 96 版本起彻底禁用它,Safari 也仅在极旧版本中支持。现在写 <input type="file" accept="image/*" capture>,大部分安卓和 iOS 设备根本不会调起摄像头,而是弹出文件选择器——这不是兼容性问题,是标准层面的失效。
用 MediaDevices.getUserMedia() 才是正解
真正可控、可编程、跨平台(iOS 17+/Android Chrome)调起摄像头的方式,是 getUserMedia()。它能拿到实时视频流,配合 <video> 预览、<canvas> 截帧,完全绕过文件系统。
常见错误现象:
- 只调用
getUserMedia({ video: true })却没处理NotAllowedError(iOS Safari 要求 HTTPS + 用户手势触发) - 忽略
videoConstraints导致默认用前置摄像头,而用户想扫后置二维码 - 没加
autoplay和muted,导致 iOS 视频黑屏(Safari 强制静音 autoplay)
基础写法示例:
立即学习“前端免费学习笔记(深入)”;
async function startCamera() {
try {
const stream = await navigator.mediaDevices.getUserMedia({
video: { facingMode: 'environment' } // 指定后置,不写则默认前置
});
videoElement.srcObject = stream;
} catch (err) {
console.error('摄像头启动失败:', err.name); // 注意 err.name 可能是 'NotAllowedError' 或 'NotFoundError'
}
}
需要拍照保存?别用 input file,用 canvas.toBlob()
如果目标是“拍一张照并上传”,走 <input type="file"> 流程会多一层用户确认、路径不可控、还可能被相册干扰。更稳的做法是:预览 → 点击按钮 → canvas 绘制当前帧 → toBlob() 生成二进制数据 → 直接 fetch 上传。
关键点:
-
canvas.getContext('2d').drawImage(videoElement, 0, 0, width, height)必须等videoElement.readyState === 4(HAVE_ENOUGH_DATA)再调用,否则画出来是黑图 - iOS Safari 对
toBlob()支持良好,但低版本 Android WebView 可能只支持toDataURL(),注意降级 - 别忘了设置
videoElement.play()—— 某些 Android 厂商定制浏览器不自动播放流
真要兼容老设备?fallback 到 input file 但别依赖 capture
如果你必须支持 iOS 14 或 Android 8 以下设备,可以做降级:先尝试 getUserMedia(),失败后退到 <input type="file" accept="image/*">。但注意:
- 绝对不要加
capture—— 它不仅无效,还会让部分旧 WebView 报错或忽略accept - 加
capture="user"或capture="environment"是非标准写法,没有任何浏览器真正识别 - 用户点击后看到的是系统相册/文件管理器,不是摄像头;这是预期行为,不是 bug
容易被忽略的地方:iOS 上 getUserMedia() 第一次调用会弹权限框,但若页面未通过 HTTPS 提供,或触发动作不在用户点击回调内(比如 setTimeout 后执行),权限请求会被静默拒绝——这个限制比 Android 严格得多。



















