2021-5-11更新:
最新版本H5调取摄像头:
2021-3-11更新:
同样还是这个h5项目,但是这次是从小程序端打开,由于之前是调取的安卓方法唤起摄像头,所以在小程序端并不适用,我又想起了使用标签来唤起摄像头
摄像头 <input type="file" accept="image/*" capture="camera">
本来是使用当前环境判断的方法,但是不知为何无法准确判断小程序环境,于是最后决定在小程序url后面加一个参数
?isWechat=1
然后进入页面时候获取这个参数做判断显示标签调取摄像头的按钮,隐藏安卓调取摄像头的按钮。
<div v-if="isWechat" class="camera-btn">
<input ref="file" type="file" class="file" accept="image/*" @change="h5CompressImage" capture="user">
<x-button style="margin-top:10px;" class="search-btn">点击拍摄</x-button>
</div>
<div v-else class="camera-btn">
<x-button style="margin-top:10px;" class="search-btn" @click.native = "checkCamera">点击拍摄</x-button>
</div>
h5CompressImage方法和下面方法差不多,只是取file是直接获取不像安卓要通过base64转为file
之前的:
part1:
最近要做一个录入人脸自拍的功能,经过一番调查,发现了以下方法可以再看浏览器端进行摄像头调取
摄像头 <input type="file" accept="image/*" capture="camera">
前置摄像头调用</h3> <input type="file" accept="image/*" capture="user"> (并没有前置)
开开心心本地测试完美运行,但是故事没有结束,然后打包上线后~
(ps:项目是安卓项目通过打开线h5页面调取摄像头拍照提交)
然后蒙了,打开安卓app测试后,发现只能打开文件选择,无法直接调取摄像头,之后无论怎么改都不可以
然后我尝试了下使用线上页面的链接,从浏览器而不是安卓app内打开,发现浏览器端是可以调取摄像头的,但是在安卓中使用它内置的浏览器打开却只能文件选择。
part2:
准备通过安卓那边提供的方法,通过方法吊起摄像头
相关代码:
在main.js中全局添加(也可以在页面单独引入)
document.addEventListener('clplusready', function() { Vue.prototype.plus = clplus;});
然后通过这段代码调取摄像头
checkCamera() {
let _this = this; //这个地方最后一步卡了我好久,一只无法获取图片,因为this指向
//调取摄像头
this.plus.clCamera.picture(function (result) {
var a = JSON.parse(result); //将拍照后返回的数组字符串转化为对象
var b = a[0].image; //获取里面的base64图片
let getData =`data:image/jpeg;base64,${b}`;//拼接成完整base64格式
_this.compressImage(getData); //把得到的base64数据传入其他方法
}, function (error) {
alert(error)
}, {
"destinationType": "0", //安卓回调设置0返回base64图片,1返回图片路径
"pictureSourceType": "1" 固定传1 是打开相机 传0是打开图库
});},
获取到base64数据后传入方法,把base64转化为文件流file格式,然后对数据进行方向和图片尺寸;大小处理
base64toFile (dataurl, filename = 'picture') {
let arr = dataurl.split(',')
let mime = arr[0].match(/:(.*?);/)[1]
let suffix = mime.split('/')[1]
let bstr = atob(arr[1])
let n = bstr.length
let u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], `${filename}.${suffix}`, {
type: mime
})
}
然后通过方法处理图片把图片旋转正,压缩等然后传入upload把图片上传
// 压缩图片 and 旋转角度纠正
compressImage (getData) {
let file = this.base64toFile(getData);
let _this = this let fileReader = new FileReader()
let img = new Image()
let imgWidth = ''
let imgHeight = ''
// 旋转角度
let Orientation = null
// 缩放图片需要的canvas
let canvas = document.createElement('canvas')
let ctx = canvas.getContext('2d')
// 图片大小 大于100KB 则压缩
const isLt2MB = file.size < 102400
// 通过 EXIF 获取旋转角度 1 为正常 3 为 180° 6 顺时针90° 9 为 逆时针90°
EXIF.getData(file, function () {
EXIF.getAllTags(this)
Orientation = EXIF.getTag(this, 'Orientation') })
// 文件读取 成功执行
fileReader.onload = function (ev) {
// 文件base64化,以便获知图片原始尺寸
img.src = ev.target.result
}
// 读取文件
fileReader.readAsDataURL(file)
// base64地址图片加载完毕后
img.onload = function () {
imgWidth = img.width
imgHeight = img.height
canvas.width = img.width
canvas.height = img.height
// 目标尺寸
let targetWidth = imgWidth
let targetHeight = imgHeight
// 不需要压缩 不需要做旋转处理
if (isLt2MB && imgWidth < 500 && imgHeight < 500 && !Orientation) return _this.upload(file)
if (isLt2MB && imgWidth < 500 && imgHeight < 500 && +Orientation === 1) return _this.upload(file) // 大于2MB 、img宽高 > 500 则进行压缩 if (!isLt2MB || imgWidth >= 500 || imgHeight >= 500) {
// 最大尺寸 let maxWidth = 500 let maxHeight = 500 // 图片尺寸超过 500 X 500 的限制 if (imgWidth > maxWidth || imgHeight > maxHeight) {
if (imgWidth / imgHeight > maxWidth / maxHeight) {
// 更宽,按照宽度限定尺寸
targetWidth = maxWidth
targetHeight = Math.round(maxWidth * (imgHeight / imgWidth))
} else {
targetHeight = maxHeight
targetWidth = Math.round(maxHeight * (imgWidth / imgHeight))
}
}
// canvas对图片进行缩放
canvas.width = targetWidth
canvas.height = targetHeight
// 图片大小超过 100k 但未旋转 则只需要进行图片压缩
if (!Orientation || +Orientation === 1) {
ctx.drawImage(img, 0, 0, targetWidth, targetHeight)
}
}
// 拍照旋转 需矫正图片
if (Orientation && +Orientation !== 1) {
switch (+Orientation) {
case 6: // 旋转90度
canvas.width = targetHeight
canvas.height = targetWidth
ctx.rotate(Math.PI / 2)
// 图片渲染
ctx.drawImage(img, 0, -targetHeight, targetWidth, targetHeight)
break
case 3: // 旋转180度
ctx.rotate(Math.PI)
// 图片渲染
ctx.drawImage(img, -targetWidth, -targetHeight, targetWidth, targetHeight)
break
case 8: // 旋转-90度
canvas.width = targetHeight
canvas.height = targetWidth
ctx.rotate(3 * Math.PI / 2)
// 图片渲染
ctx.drawImage(img, -targetWidth, 0, targetWidth, targetHeight)
break
}
}
// 调用接口上传
// _this.upAppUserFaceByBase64()
// 通过文件流格式上传
canvas.toBlob(function (blob) {
_this.upload(blob)
}, 'image/jpeg', 1)
}
},
上传文件流处理
得到的file
var formdata = new FormData();
formdata.append("file",file,file.name)
然后上传formdata