
本文详解如何在基于 navigator.mediaDevices.getUserMedia 的 Web QR 扫描应用中正确启用并验证相机自动对焦(focusMode),涵盖约束配置、设备兼容性判断、动态约束应用及常见失效原因排查。
本文详解如何在基于 `navigator.mediadevices.getusermedia` 的 web qr 扫描应用中正确启用并验证相机自动对焦(focusmode),涵盖约束配置、设备兼容性判断、动态约束应用及常见失效原因排查。
在 Web 端实现高精度 QR 码扫描时,相机能否稳定对焦是识别小尺寸或近距离码的关键。然而,许多开发者发现即使显式设置 focusMode: "continuous",实际效果仍不理想——画面模糊、扫码失败。这并非代码逻辑错误,而是受限于浏览器、操作系统与硬件的协同能力。以下为经过实测验证的完整解决方案。
✅ 正确启用自动对焦的三步关键实践
1. 先检测支持性,再设置约束
focusMode 并非所有设备都支持。必须通过 getSupportedConstraints() 显式检查,并仅在支持时注入约束:
const track = stream.getVideoTracks()[0];
const supported = track.getCapabilities?.();
if (supported && supported.focusMode) {
console.log('Focus mode supported:', supported.focusMode);
await track.applyConstraints({
focusMode: 'continuous'
});
} else {
console.warn('Auto-focus not supported on this device');
}
⚠️ 注意:getSupportedConstraints() 返回的是全局可用约束列表,而 track.getCapabilities() 才反映当前视频轨道的实际能力(含 focusMode 取值范围),后者更准确。
2. 约束应直接作用于 getUserMedia,而非 applyConstraints 后补
你原代码中在 getUserMedia 成功后才调用 applyConstraints,且约束对象结构有误(如 advanced 数组嵌套不合法)。正确做法是将 focusMode 直接写入初始 constraints 对象:
navigator.mediaDevices.getUserMedia({
video: {
facingMode: { exact: 'environment' },
focusMode: { ideal: 'continuous' }, // ✅ 直接在此声明
width: { ideal: 1280 },
height: { ideal: 720 },
frameRate: { ideal: 15 }
}
})
? 规范依据:Media Capture and Streams spec 明确 focusMode 是一级约束项,不可置于 advanced 数组内(该字段已废弃)。
3. 避免硬编码宽高比与分辨率冲突
你代码中同时设置了 width: 900, height: 900 和 advanced: [{ width: 1920, height: 1280 }],易触发约束冲突导致浏览器降级处理(忽略对焦)。推荐策略:
- 优先使用 ideal 而非 exact(提高兼容性);
- 移除冗余 advanced;
- 对扫码场景,1280×720 或 1920×1080 更利于小码识别,而非正方形裁剪。
✅ 完整可运行示例(含容错与日志)
async function initCamera() {
try {
const stream = await navigator.mediaDevices.getUserMedia({
video: {
facingMode: 'environment',
focusMode: { ideal: 'continuous' },
width: { ideal: 1280 },
height: { ideal: 720 },
frameRate: { ideal: 15 }
}
});
const video = document.getElementById('video');
video.srcObject = stream;
const track = stream.getVideoTracks()[0];
const capabilities = track.getCapabilities?.();
if (capabilities?.focusMode?.includes?.('continuous')) {
await track.applyConstraints({ focusMode: 'continuous' });
console.log('✅ Continuous focus enabled');
} else {
console.warn('⚠️ Focus mode not available; using default behavior');
}
} catch (err) {
console.error('❌ Camera init failed:', err.name, err.message);
}
}
? 常见失效原因与应对建议
| 问题现象 | 根本原因 | 解决方案 |
|---|---|---|
| focusMode 设置无效 | iOS Safari / Android WebView 不支持 continuous(仅支持 manual 或忽略) | 检测 capabilities.focusMode,对 iOS 尝试 setManualZoom + focusDistance 配合手动调焦(需用户交互) |
| 近距离仍模糊 | 物理镜头最小对焦距离限制(通常 ≥10cm) | 提示用户保持 ≥15cm 距离;结合 torch 补光提升对比度 |
| 扫码延迟高 | Canvas 尺寸过大(1200×1200)导致 drawImage 性能瓶颈 | 将 canvas 设为 640×480,仅绘制视频流有效区域(video.videoWidth/Height) |
? 总结
Web 端相机对焦能力高度依赖底层平台支持:Chrome on Android 支持最佳,iOS Safari 限制最多。没有“银弹”式聚焦方案,但可通过“检测 → 合理约束 → 容错降级 → UX 引导”四步显著提升成功率。 切勿依赖第三方库自动处理对焦——它们同样受限于浏览器 API 能力边界。最终,清晰的调试日志(getCapabilities、getSettings)和真实设备测试,才是解决模糊问题的核心路径。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











