需求是小程序这边先拍摄露出手腕的照片,然后传给后端,调百度识别的api,根据返回的手腕位置,显示手表的贴图(可以拖拽旋转之类的)最后可以生成海报,保存图片到手机。
前端这边的技术点分别有

<camera class="camera"></camera>
<!-- 拍照按钮 -->
<view class="takePhoto" @click="takePhoto">
<view class="inner"></view>
</view>
//js里面写
methods: {
// 拍照
takePhoto() {
const ctx = wx.createCameraContext()
ctx.takePhoto({
quality: 'high',
success: (res) => {
// console.log(res)
this.imagePath = res.tempImagePath//保存照片临时地址
}
})
},
}
上传图片
参考文档参考文档

将红框里面的url换成后端给你的上传接口就可以啦,记得一定要去小程序开发后台配一下uploadFile合法域名,不然死活传不上去的!!!


图片拖拽功能
生成海报
这两个功能我使用了组件小程序组件-canvas拖拽组件 真的贼牛逼
但是我们的需求是,根据接口返回的位置,在手腕那里直接显示手表的图片,所以还要调整一下。
<!-- canvas -->
<view class="result" v-show="imagePath&&(!showPoster)">
<button @click="saveImg">生成海报</button>
<button @click="again">重新拍摄</button>
<canvas-drag ref="canvasRef" id="canvas-drag" :graph="graph" :width="photoX" :height="photoY"
enableUndo="true">
</canvas-drag>
</view>
首先要注意的是,一定要用v-show 而不是v-if 不然this.$refs取不到的
然后还要注意,百度识别返回的手腕坐标,是手腕中心位置距离图片左上角的位置,单位是px。所以我们用的时候需要
uni.uploadFile({
url:'写后端给你的url',//返回位置和手掌大小
filePath: imagePath,
name: 'file',
formData: {
'user': 'test'
},
success: (res) => {
var jsarr = JSON.parse(res.data)
if (jsarr.code != 200) {
uni.showModal({
title: '提示',
content: '人体数据识别失败,请重新拍照',
showCancel: false,
success: (res) => {
if (res.confirm) {
console.log('用户点击确定');
this.imagePath = ''
}
}
});
} else {
console.log('xxxx',jsarr.data.wrist.x)
this.watchX = jsarr.data.location.width/2
this.watchY = this.watchX
//贴图初始位置
this.initialX = jsarr.data.wrist.x / 2 -this.watchX/2
this.initialY = jsarr.data.wrist.y / 2 -this.watchX/2
//控制贴图移动位置,我写死了
this.minX=this.initialX-this.watchX/30
this.maxX=this.initialX+this.watchX/10*9
this.minY=this.initialY-this.watchY/30
this.maxY=this.initialY+this.watchY/10*9
this.isBody = true
this.onChangeBgImage()
console.log("xy", this.initialX, this.initialY)
}
}
})
//展示图片背景
onChangeBgImage() {
this.$refs.canvasRef.changeBgImage(this.imagePath)
this.onAddWatch()
},
//显示手表
onAddWatch() {
this.setData({
graph: {
//贴图大小
w: this.watchX,
h: this.watchY,
//贴图坐标
x: this.initialX,
y: this.initialY,
rotate: this.rotate,
//贴图位置限制
minX:this.minX,
maxX:this.maxX,
minY:this.minY,
maxY:this.maxY,
type: 'image',
//贴图地址
url: "/static/images/watchPhoto.png"
}
});
},
组件里面需要加上对贴图移动的限制,找到move()
move(e) {
const {
x,
y
} = e.touches[0];
if (this.tempGraphArr && this.tempGraphArr.length > 0) {
isMove = true; // 有选中元素,并且有移动时,设置移动标识
const currentGraph = this.tempGraphArr[this.tempGraphArr.length - 1];
if (currentGraph.action === 'move') {
currentGraph.centerX = this.currentGraph.centerX + (x - this.currentTouch.x);
currentGraph.centerY = this.currentGraph.centerY + (y - this.currentTouch.y); // 使用中心点坐标计算位移,不使用 x,y 坐标,因为会受旋转影响。
//控制图片移动位置
if(currentGraph.centerX<=this.graph.minX){
currentGraph.centerX=this.graph.minX
}
if(currentGraph.centerX>this.graph.maxX){
currentGraph.centerX=this.graph.maxX
}
if(currentGraph.centerY<=this.graph.minY){
currentGraph.centerY=this.graph.minY
}
if(currentGraph.centerY>this.graph.maxY){
currentGraph.centerY=this.graph.maxY
}
if (currentGraph.type !== 'text') {
currentGraph.x = currentGraph.centerX - this.currentGraph.w / 2;
currentGraph.y = currentGraph.centerY - this.currentGraph.h / 2;
}
} else if (currentGraph.action === 'transform') {
console.log('图片缩放')
currentGraph.transform(this.currentTouch.x, this.currentTouch.y, x, y, this.currentGraph);
} // 更新4个坐标点(相对于画布的坐标系)
currentGraph._rotateSquare();
this.draw();
}
},
最后生成海报的功能,也是直接调组件的方法就可以了
/**
* 导出当前画布为模板
*/
saveImg() {
uni.showLoading({
mask: true
})
this.$refs.canvasRef.exportFun().then(imgArr => {
console.log(JSON.stringify(imgArr));
this.showPoster = imgArr
uni.hideLoading()
}).catch(e => {
console.error(e);
});
},

大概就是这样子啦