最近有个需求是拍照识别Vin码,为了识别准确度,要求前端只上传取景框内的内容给后端识别.
通过一天多的碰壁(微信开发者工具,懂的都懂),终于在各种论坛的各种不起眼的地方摸出了一套可以正常使用的流程.
总流程如下:
-
使用<carema>组件唤起相机
-
点击拍照按钮拍照,使用 CameraContext.takePhoto(Object object)函数拍照,并在success回调中保存图片地址res.tempImagePath
- 获取canvas实例,传给自定义函数init()
takePhoto() {
const ctx = wx.createCameraContext()
ctx.takePhoto({
quality: 'high',
success: (res) => {
console.log(res.tempImagePath)
this.setData({
tFlag: false,
iPath: res.tempImagePath
})
wx.createSelectorQuery()
.select('#mycanvas')
.fields({
node: true,
size: true
}, (res) => {
console.log(res)
const canvas = res.node
const ctx2 = canvas.getContext('2d');
this.init(ctx2, canvas)
})
.exec()
},
fail: (err) => {
console.log(err)
}
})
}
-
使用Canvas.createImage()函数创建一个image对象,然后给image对象(src)赋值,在img.onload回调中继续下一步
-
获取刚刚拍的照片的尺寸(img.width/img.height),然后根据取景框相对于camera组件的位置和大小计算出图片对应部分的截取的定位和尺寸.比如我的取景框的position是top:36.5%,就是c_y = img.height*0.365;
-
前面步骤都完成了基本没有大问题了,接下来就是绘制canvas然后保存为图片,存到本地
init(ctx, canvas) {
let img = canvas.createImage()
img.src = this.data.iPath
img.onload = (e) => {
this.setData({
width_t: img.width,
height_t: img.height
})
let c_x = img.width * 0.05
let c_w = img.width * 0.89
let c_y = img.height * 0.365
let c_h = img.height * 0.12
console.log(c_x, c_y, c_w, c_h)
//截取图片指定部分并绘制到canvas
ctx.drawImage(img, c_x, c_y, c_w, c_h, 0, 0, 300, 300 * (c_h / c_w))//width固定为300,按比例计算出height
//将canvas内容保存为图片
wx.canvasToTempFilePath({
canvas: canvas,
width: 300,
height: 300 * (c_h / c_w),
fileType: 'png',
success: (res) => {
wx.saveImageToPhotosAlbum({ //将图片保存到本地相册
filePath: res.tempFilePath,
})
const imgPath = String(res.tempFilePath)
//上传到接口
this.uploadimg(imgPath)
},
fail: (res) => {
console.log(res)
}
})
}
img.onerror = (e) => {
console.error('err:', e)
}
}
写得比较潦草,不懂的可以评论问我