记录一下遇到需求和解决
1.前段时间遇到一个需求
在图中需要一个圈选功能就类似圈中想要的商品下单,刚看到这个需求的时候还是一头雾水,画那种矩形框还是简单的,可以需要裁剪矩形框内的内容不知从何下手,前端老大让我使用了一个叫 welCropper的插件使用截图,花了几天研究做了一个类似的功能可以效果差值甚远,没有圈选的功能只有一个简单的拉住矩形框截出图片,想着抱着侥幸最后果然还是被退回来了,点了一定要和圈选功能一样,因为canvas接触的少,之前还傻到用背景图定位上去,原生canvas的api就可以解决了,直接上代码吧
实现
canvas的手指触摸动作开始
touchStart: function(e) {
this.setData({
minX: e.changedTouches[0].x, //定义矩形左上和右下两个点坐标
minY: e.changedTouches[0].y,
maxX: e.changedTouches[0].x,
maxY: e.changedTouches[0].y,
})
//得到触摸点的坐标
this.startX = e.changedTouches[0].x
this.startY = e.changedTouches[0].y
this.context = wx.createCanvasContext("moveCanvas", this)
this.context.setStrokeStyle(this.data.color)
this.context.setLineWidth(this.data.pen)
this.context.setLineCap('round') // 让线条圆润
this.context.beginPath()
},
//手指触摸后移动
touchMove: function(e) {
var minX = this.data.minX
var minY = this.data.minY
var maxX = this.data.maxX
var maxY = this.data.maxY
var startX1 = e.changedTouches[0].x
var startY1 = e.changedTouches[0].y
if (startX1 < minX) minX = startX1; //判断当前的点与原来存的两个点做比较
if (startX1 > maxX) maxX = startX1;
if (startY1 < minY) minY = startY1;
if (startY1 > maxY) maxY = startY1;
this.context.moveTo(this.startX, this.startY)
this.context.lineTo(startX1, startY1)
this.context.stroke()
this.startX = startX1;
this.startY = startY1;
//只是一个记录方法调用的容器,用于生成记录绘制行为的actions数组。context跟不存在对应关系,一个context生成画布的绘制动作数组可以应用于多个
wx.drawCanvas({
canvasId: 'moveCanvas',
reserve: true,
actions: this.context.getActions() // 获取绘图动作数组
})
this.data.contextCount++;
this.setData({
minX: minX,
minY: minY,
maxX: maxX,
maxY: maxY,
})
},
//手指触摸动作结束
touchEnd: function() {
this.context.drawImage(this.data.tempFilePaths, 0, 0, windowWidth, windowHeight * 0.5) //windowWidth windowHeight 为当前屏幕的宽高具体的获取的api 这里就不介绍了 自行百度
this.context.draw() //每次结束的时候清空原有的画布 重新drawImage
wx.canvasToTempFilePath({ //把当前画布指定区域的内容导出生成指定大小的图片,并返回文件路径
x: this.data.minX,
y: this.data.minY,
width: this.data.maxX - this.data.minX,
height: this.data.maxY - this.data.minY,
destWidth: this.data.maxX - this.data.minX,
destHeight: this.data.maxY - this.data.minY,
canvasId: 'moveCanvas',
success: function (res) {
console.log(res.tempFilePath)
var imgarr = that.data.imgarr; //获取存临时路径的数组 原来为空
var img = { 'img': res.tempFilePath,'num':1,'havmin':3,'havmax':6};
imgarr.push(img);
var views = 'img' + String(imgarr.length - 1); //这里是scroll-view的scroll-into-view的位置 设置滚动条位置滚动条位置 views 为scroll-view新的内容的id
// console.log(viewsss);
that.setData({
imgarr: imgarr,
viewsss: viewsss
})
}
})
var that=this;
var arr=this.data.arr; //定义的存所有矩形两点的数组
var arr1 = [this.data.minX, this.data.minY, this.data.maxX, this.data.maxY];
arr.push(arr1)
this.setData({
arr: arr
})
for (var i = 0; i < arr.length;i++){ //遍历这个数组
this.context.beginPath();
this.context.setLineWidth(2);
if (i == arr.length-1){ //新的一个为红色 之前的为绿色
this.context.setStrokeStyle("red");
}
else{
this.context.setStrokeStyle("green");
}
this.context.rect(arr[i][0], arr[i][1], arr[i][2] - arr[i][0], arr[i][3] - arr[i][1]);
this.context.stroke();
this.context.draw(true) //带参数true 不清空画布
}
},
备注的很清楚了,加载的时候都需要给canvas添加图片使用drawImage。配合上wx.canvasToTempFilePath把当前画布指定区域的内容导出生成指定大小的图片,并返回文件路径,这样就可以使用临时文件路径上传到服务器中。加载矩形的同时需要清除画笔路线,在touchEnd的时候重新调用drawImage并且draw不带参数清空画布,循环存的矩形数组生成到页面上,到这就结束了 。有问题可以在下方留言,看到都会回复。
···········································································································································
补上里面的一个bug吧,安卓手机圈选的时候会出现问题,圈选的时候之前的路径不能完全清空,导致保存的图片带上路线,在保存的时候把 wx.canvasToTempFilePath 写在延时器中,延时执行就可以完美解决兼容性问题。好像是这样的,过去挺久了突然看到自己的帖子顺手补上。希望能帮到大家!
setTimeout(() => {
//事件
}, 200);