小程序的canvas 实现裁剪图片、圈选功能,drawImage和canvasToTempFilePath的配合使用。

记录一下遇到需求和解决

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);
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值