需求说明:在采集用户的身份证件信息时,如果选择拍摄,增加取景框,拍摄完成后需要旋转角度再上传
之前查过相关资料,自我感觉,最简单的办法就直接使用camera组件内嵌cover-view组件,并根据点击事件获取拍照采集的类型是正面亦或是反面,从而修改取景框的背景图片显示
<!-- 上传身份证 -->
A页面
<view class="idPortrait">
<text class="business-txt">上传身份证(人像面)</text>
<view class="business-img">
<image mode='aspectFill' src="{{image2}}"/>
</view>
<button class="business-btn" bindtap="idImage" data-type="idcard_front">上传身份证(人像面)</button>
</view>
<!-- 授权代理人身份证(国徽) -->
<view class="nationalEmblem">
<text class="business-txt">上传身份证(国徽面)</text>
<view class="business-img">
<image mode='aspectFill' src="{{image3}}"/>
</view>
<button class="business-btn" bindtap="idImage" data-type="idcard_back">上传身份证(国徽面)</button>
</view>
B页面
<camera
device-position="back"
flash="off"
binderror="cameraError"
class="cameraPhoto_camera"
style="height:{{cameraHeight}}px">
<cover-view class="controls" style="width: 100%;height: 100%;">
<cover-view class="controls2-bgcolor">
<!-- 人像照 -->
<cover-image wx:if='{{photoType == "idcard_front"}}' src="../../../resource/camera_front.png" />
<!-- 国徽照 -->
<cover-image wx:else src="../../../resource/camera_side.png" />
</cover-view>
</cover-view>
</camera>
<view class="cameraPhoto_bottom">
<view class="wrap">
<view bindtap="cancel">取消</view>
<view bindtap="takePhoto">
<image class="wrap_ok" src="../../../resource/camera_btn_icon.png"></image>
</view>
<view bindtap="chooseImage">相册</view>
</view>
</view>
由于不在同一个界面,又需要进行两次拍摄,所以,不能使用常规的页面跳转传值逻辑,我的方案是在B页面拍摄完成后,通过getCurrentPages()函数,在进行navigateBack返回A界面时,调用A页面的传值方法,以避免因为两次拍摄,而导致刷新页面数据的问题,逻辑如下
B界面
onLoad(options) {
this.setData({
photoType:options.type
})
if (wx.createCameraContext) {
this.setData({
cameraContext:wx.createCameraContext()
})
}
},
cameraError(e){
const that = this;
wx.getSetting({
success(res) {
if (!res.authSetting["scope.camera"]) {
wx.showModal({
title: '提示',
content: '请开启摄像头权限,否则无法拍照',
confirmText: '去开启',
success(res) {
if (res.confirm) {
wx.openSetting({
success(res) {
if (res.authSetting["scope.camera"]) {
wx.navigateBack({
delta: 1
})
} else {
wx.navigateBack({
delta: 1
})
}
}
})
} else if (res.cancel) {
wx.navigateBack({
delta: 1
})
}
}
})
}
}
})
},
cancel(){
wx.redirectTo({
url: '../index'
})
},
takePhoto(){
let that = this
this.data.cameraContext.takePhoto({
quality: 'normal',
success: (res) => {
let pages = getCurrentPages();
let prevPage = pages[pages.length - 2];
wx.navigateBack({
delta: 1,
success: function () {
//调用前一个页面的上传图片方法,最后一个传参为是否需要旋转,只会针对拍照的图片进行旋转操作
prevPage.imgUpload(that.data.photoType,res.tempImagePath,true)
}
})
},
fail: (err) => {
wx.showToast({
title:'拍照失败,请检查系统是否授权',
icon: 'none',
duration: 1200
})
}
})
},
chooseImage(){
let that = this
wx.chooseImage({
count: 1,
sizeType: ['original', 'compressed'],
sourceType: ['album'],
success: (res) => {
let pages = getCurrentPages();
let prevPage = pages[pages.length - 2];
wx.navigateBack({
delta: 1,
success: function () {
//调用前一个页面的上传图片方法。
prevPage.imgUpload(that.data.photoType,res.tempFilePaths[0],false)
}
})
},
fail: (err) => {}
});
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
let systemInfo = wx.getSystemInfoSync()
this.setData({
windowHeight:systemInfo.windowHeight,
cameraHeight:systemInfo.windowHeight - 100
})
},
A界面
idImage: function (e) {
var that = this
wx.showActionSheet({
itemList: ['拍照','从相册中选取'],
itemColor: '#',
success(res) {
if (res.tapIndex === 0) {
//调用camera组件,即B界面
wx.navigateTo({
url: './index?type='+e.currentTarget.dataset.type,
});
} else if (res.tapIndex === 1) {
wx.chooseImage({
count: 1,
sizeType: ["compressed"],
sourceType: ['album'],
success: function (res1) {
let filePath = res1.tempFilePaths[0]
that.imgUpload(e.currentTarget.dataset.type,filePath,false)
},
fail: function () {
}
})
}
}
})
},
imgUpload(type,filePath,rotateval){
let that = this;
wx.showLoading({
title:'信息采集中,请稍候',
mask:true
})
if (rotateval) {
let url = filePath;
wx.getImageInfo({
src: url,
success:res=>{
let canvasContext = wx.createCanvasContext('my-canvas', this)
let width = res.width;
let height = res.height;
this.setData({
canvasWidth: width,
canvasHeight: height,
})
canvasContext.translate(width / 2, height / 2)
canvasContext.rotate(270 * Math.PI / 180);
canvasContext.drawImage(url, -width / 2, -height / 2, width, height);
canvasContext.draw(false, () => { // 将之前在绘图画到 canvas 中
setTimeout(function () {
//小程序版本中对于Canvas空间绘制图片,存在bug,效率比较低。canvasToTempFilePath接口最大的坑
wx.canvasToTempFilePath({ // 把当前画布指定区域的内容导出生成指定大小的图片。在 draw() 回调里调用该方法才能保证图片导出成功。
canvasId: 'my-canvas',
success(res) {
filePath = res.tempFilePath
that.wxUploadApi(type,filePath)
}
}, this)// 在自定义组件下,当前组件实例的this,以操作组件内 canvas 组件
},300);
})
}
})
}else{
that.wxUploadApi(type,filePath)
}
},
wxUploadApi(type,filePath){
let that = this
//此处的header和token属接口配置需要,按需添加
let token = wx.getStorageSync("token");
let header = {}
header['Accept'] = 'application/json';
header['WxAuthorization'] = token;
if (type == 'idcard_front') {
let formData = {
'type':type,
'isTemple':"false"
}
wx.uploadFile({
url:that.data.baseUrl,
filePath: filePath,
name: 'file',
header: header,
formData:formData,
withCredentials: true,
success(res2) {
wx.hideLoading()
let data = JSON.parse(res2.data)
console.log(data);
if(data.code == 200) {
that.setData({
....
})
}else{
wx.hideLoading()
wx.showToast({
icon:'error',
title: '上传身份证正面错误,请重新上传',
duration: 1200
})
}
},
fail(res) {
wx.hideLoading()
wx.showToast({
icon:'error',
title: '上传身份证正面失败,请重新上传',
duration: 1200
})
// reslogin(err)
},
complete() {
}
})
}else if(type == 'idcard_back'){
let formData = {
'type':type,
}
wx.uploadFile({
url:that.data.baseUrl,
filePath: filePath,
name: 'file',
header: header,
formData:formData,
withCredentials: true,
success(res2) {
wx.hideLoading()
let data = JSON.parse(res2.data)
if(data.code == 200) {
that.setData({
...
})
}else{
wx.hideLoading()
wx.showToast({
icon:'error',
title: '上传身份证背面错误,请重新上传',
duration: 1200
})
}
},
fail(res) {
wx.hideLoading()
wx.showToast({
icon:'error',
title: '上传身份证背面失败,请重新上传',
duration: 1200
})
},
complete() {
}
})
}
},
然后在进行旋转过程后发现个极其恶心的bug,由于canvasToTempFilePath返回的是本地临时路径,无法查看图片是什么样的,只有传到后台服务器后,后台成功识别才能返回可以线上浏览的图片路径,我数次测试后台接口那边就是识别不通过,但只要不经过旋转,而直接拿相册或者拍照组件返回临时路径上传,就是正常的,后来我才发现经过画布组件旋转后上传的图片就是纯黑的,也曾试过清除画布内容、重置画面背景色等操作,结果就是,无效,只有再加上延时器后才能正常导出图片,我也是服了