踩坑日常
最近公司需要做一个拍照扫描的功能,第一版使用input type=file,直接调用原生相机;然后测试大佬觉得链路太长,点击按钮->出现选择栏->选择相机->拍照点击使用->回到页面;作为卑微前端,改,选中了WebRTC的navigator.mediaDevices.getUserMedia,其他博客都有介绍,不多赘述;直接上干货。毕竟直接能拿来用的博客才是好代码。
- 参数设置
用法其他博客都有介绍
(tips: 在华为鸿蒙系统中,相机像素的宽高比是反过来的,类似电脑那种摄像头,还有近处的贼模糊,只能远景,踩坑+1)
const { clientWidth, clientHeight } = videoEl.value
const params = isHarmonyOS
? {
width: { min: 1080, ideal: 1440, max: 2880, exact: clientWidth },
height: { min: 2400, ideal: 3840, max: 6400, exact: clientHeight },
}
: {
width: { min: 1280, ideal: 1440, max: 2560 },
height: { min: 600, ideal: 720, max: 1440 },
}
const constraints = {
video: {
...params,
frameRate: { min: 30, ideal: 60, max: 120 },
facingMode: 'environment', // 强制后置摄像头
}
}
- 打开摄像头之后模糊
(tips:加上自动聚焦,好的测试才能出好的产品,测试很认真,手动认真脸,优化+1)
videoEl.value.focus()
- 续1
开始绘制canvas,不出意外的又要进坑了
(tips:遥遥领先,调整完像素比,以为没事了,天真了,绘制完天塌了,图片直接变形,踩坑+1 )
const { clientWidth, clientHeight, videoWidth, videoHeight } = videoEl.value
const canvas = document.createElement('canvas')
const devicePixelRatio = window.devicePixelRatio || 3
const scaleNum = videoHeight / videoWidth
const canvasHeight = clientWidth * devicePixelRatio * scaleNum
canvas.width = isHarmonyOS ? clientHeight * devicePixelRatio : clientWidth * devicePixelRatio
canvas.height = isHarmonyOS ? clientWidth * devicePixelRatio : canvasHeight
- 拍照之后绘制canvas
(tips:又是遥遥领先,第一次拍出来的是空白透明图片,一度以为没拍出来,踩坑+1)
const checkIfImageIsTransparent = async (imageData: any): Promise<boolean> => {
return new Promise((resolve) => {
for (let i = 0; i < imageData.data.length; i += 4) {
if (imageData.data[i + 3] !== 0) {
resolve(false)
return
}
}
resolve(true)
})
}
checkIfImageIsTransparent(imageData).then((res: boolean) => {
if (res) {
Message('请重新拍摄')
} else {
// 业务代码
}
})
- 页面切出打开原生相机,切回来后黑屏
(tips:这次是安卓,ios兼容性好点,优化+1)
页面切回来后先关掉其他的视频流,然后再次获取navigator.mediaDevices.getUserMedia视频流
currentStream navigator.mediaDevices.getUserMedia获取到的视频流
if (currentStream.value) {
const tracks = currentStream.value?.getTracks()
tracks.forEach((track:any) => {
track.stop()
})
currentStream.value = null
}
每次打开页面都会询问下权限获取,产品觉得太麻烦,只想询问一次,(tips:请恕臣妾做不到啊,手动图)
大佬有研究过的可以留言py一波。
暂时就是这些,over!!!
(直接用,出bug哪有心思慢慢看文档)