美文网首页
006-小程序图片滑动、缩放加canvas打印

006-小程序图片滑动、缩放加canvas打印

作者: 垒虚 | 来源:发表于2018-08-01 23:41 被阅读0次

    一:这段时间一直在学习微信小程序,近期也多有遇到小程序有关于图片与canvas的坑,

    二:说明一下需求吧:首先要有两张图片,其中一张中间部分是透明的图片A,另一张是完整的图片B;现在图片A在上面,图片B在下面,当手指在图片A上移动时,图片B要跟着移动,同时还要做到可以双指缩放;在调整好位置之后,还要用canvas把完成的结果图片打印出来;

    三:解决问题:

    1:页面布局

    //移动的事件最好还是用catch来
    //因为小程序回调的参数是用px来计算的,所以这里就不用rpx了,如果一定要用,请做好不同手机的适配
    <view class='img' catchtouchstart='touchstart' catchtouchmove='touchmove' catchtouchend='touchend'>
      <image mode='aspectFill' class='img zIndex' src='{{图片A}}'></image>
    //这里想用margin用margin,想用top、left就用top、left,感觉是一样的,transform应该也可以,
      <image style='margin-left:{{marginLeft}}px;margin-top:{{marginTop}}px;height:{{imgHeight}}px;width:{{imgWidth}}px' src='{{图片B}}' class='img'></image>
    </view>
    .img{
      height: 100vh;
      width: 100%;
      position: absolute;
      top: 0;
      left: 0;
      display: flex;
      box-sizing: border-box
    }
    .zIndex{
      z-index: 5
    }
    

    2:移动,缩放的方法

    // 开始点击
        touchstart(e) {
          this.setData({
            lastTouchPoint: { x: 0, y: 0 },
            oldDist: 0
          })
        },
        /**
         * 计算x轴上的双指中心点比例
         */
        _calcXRatio: function (event) {
          let xRatio = ((event.touches[0].clientX + event.touches[1].clientX) / 2 - this.data.marginLeft) / this.data.imgWidth
          return xRatio
        },
        /**
         * 计算y轴上的双指中心点比例
         */
        _calcYRatio: function (event) {
          let yRatio = ((event.touches[0].clientY + event.touches[1].clientY) / 2 - this.data.marginTop) / this.data.imgHeight
          return yRatio
        },
        //移动和放大
        _zoom: function (f, event) {
          let xRatio = this._calcXRatio(event)
          let yRatio = this._calcYRatio(event)
          let maxMultiple = this.data.maxMultiple
          let minMultiple = this.data.minMultiple
          //minMultiple是最小倍数,可以自己设置
          if (this.data.imgWidth <= this.data.windowWidth * minMultiple && f < 1) {
            let ratio = this.data.windowWidth / this.data.imgWidth
            this.setData({
              imgWidth: this.data.imgWidth * ratio * minMultiple,
              imgHeight: this.data.imgHeight * ratio * minMultiple
            })
            return;
          }
          if (this.data.imgHeight <= this.data.view_height * minMultiple && f < 1) {
            let ratio = this.data.view_height / this.data.imgHeight
            this.setData({
              imgWidth: this.data.imgWidth * ratio * minMultiple,
              imgHeight: this.data.imgHeight * ratio * minMultiple
            })
            return;
          }
          //maxMultiple是最大倍数,可以自己设置
          if (this.data.imgWidth >= this.data.windowWidth * maxMultiple && f > 1) {
            let ratio = this.data.windowWidth / this.data.imgWidth
            this.setData({
              imgWidth: this.data.imgWidth * ratio * maxMultiple,
              imgHeight: this.data.imgHeight * ratio * maxMultiple,
            })
            return;
          }
          if (this.data.imgHeight >= this.data.windowHeight * maxMultiple && f > 1) {
            let ratio = this.data.windowHeight / this.data.imgHeight
            this.setData({
              imgWidth: this.data.imgWidth * ratio * maxMultiple,
              imgHeight: this.data.imgHeight * ratio * maxMultiple,
            })
            return;
          }
          this.setData({
            //此处的ratio为双指中心点在图片的百分比
            marginLeft: this.data.marginLeft + xRatio * this.data.imgWidth * (1 - f),
            marginTop: this.data.marginTop + yRatio * this.data.imgHeight * (1 - f),
            imgWidth: this.data.imgWidth * f,
            imgHeight: this.data.imgHeight * f,
          })
        },
    
        _spacing: function (event) {
          let x = event.touches[0].clientX - event.touches[1].clientX;
          let y = event.touches[0].clientY - event.touches[1].clientY;
          return Math.sqrt(x * x + y * y);
        },
        //移动距离
        touchmove(e) {
          let moveX = e.changedTouches[0].clientX
          let moveY = e.changedTouches[0].clientY
          let oldDist = this.data.oldDist;
          let newDist = this.data.newDist;
          let lastTouchPoint = this.data.lastTouchPoint
          //单指移动事件
          if (e.touches.length == 1) {
            if (lastTouchPoint.x == 0 && lastTouchPoint.y == 0) {
              lastTouchPoint.x = e.touches[0].clientX
              lastTouchPoint.y = e.touches[0].clientY
              this.setData({
                lastTouchPoint,
              })
            } else {
              let xOffset = e.touches[0].clientX - lastTouchPoint.x
              let yOffset = e.touches[0].clientY - lastTouchPoint.y
              lastTouchPoint.x = e.touches[0].clientX
              lastTouchPoint.y = e.touches[0].clientY
              this.setData({
                marginTop: this.data.marginTop + yOffset,
                marginLeft: this.data.marginLeft + xOffset,
                lastTouchPoint
              })
            }
          } else if (e.touches.length == 2) {
            if (oldDist == 0) {
              oldDist = this._spacing(e);
              this.setData({
                oldDist
              })
            } else {
              newDist = this._spacing(e);
              if (newDist > oldDist + 1) {
                this._zoom(newDist / oldDist, e);
                oldDist = newDist;
                this.setData({
                  oldDist,
                  newDist
                })
              }
              if (newDist < oldDist - 1) {
                this._zoom(newDist / oldDist, e);
                oldDist = newDist;
                this.setData({
                  oldDist,
                  newDist
                })
              }
            }
          }
    
        },
        //移动结束
        touchend(e) {
        //移动结束这个方法可以根据自己的需求来做,不是必要的
        },
    

    3:重头戏来了,图片的canvas打印,有些人会说如果想用canvas打印你干嘛前面不用canvas来写呢;这里有个问题,canvas上面如果想加东西只能加cover-view,但是cover-view有各种限制和不足,所以当你加的东西不影响到最后生成的图的时候可以用用这个,其他的确实直接canvas简单方便

        //  因为canvas用的也是px,如果前面用其他单位的话,记得换算
        let backImgWidth = this.data.backImgWidth//图片A的宽度
        let backImgHeight = this.data.backImgHeight//图片A的高度
        let imgWidth = this.data.imgWidth//图片B的宽度
        let imgHeight = this.data.imgHeight//图片B的高度
        let windowWidth = this.data.windowWidth//手机屏的宽度
        let windowHeight = this.data.windowHeight//手机屏的高度
        let marginTop = this.data.marginTop
        let marginLeft = this.data.marginLeft
        let that = this
        //因为屏幕的长宽比实在是太多了,而且为了图片不变形,一般都会用裁剪的功能,所以,我们要知道这里图片A到底被裁了多少
        let distance = backImgHeight * windowWidth / backImgWidth - windowHeight 
        //现在基本就是绘图了
       const ctx = wx.createCanvasContext('img')
        //花型图片因为底图片裁剪,所以还有一段裁剪掉的对上距离要加上
        ctx.drawImage(图片B, marginLeft, marginTop + distance/2, imgWidth, imgHeight)
        //底图片高度应为会自定义缩放,所以必须在这里就将图片按比例算好大小
        ctx.drawImage('图片A', 0, 0 , windowWidth, backImgHeight * e.windowWidth / backImgWidth)
        //生成图片是要把裁剪掉的距离给去掉的同时,高度也要和前面的一样
        //这里要用false,用true会保留原来的图片样式,那就有的玩了
        ctx.draw(false, (e) => {
          wx.canvasToTempFilePath({
            x: 0,
            y: distance / 2,
            width: windowWidth,
            height: windowHeight ,
            destWidth: windowWidth,
            destHeight: windowHeight,
            canvasId: 'img',
            success: (res) => {
              //图片生成成功了
              console.log(res)
            },
            fail:(res)=>{
              console.log(res)
            }
          }, that)
        })
       //对了还留了一个坑,小程序你想要canvas正常使用,你就必须在布局的时候给它位置;
       //还有canvas的canvas-id一定要和打印的一样
       <canvas class='canvas' canvas-id='img'></canvas>
    

    这样以来算可以正常使用

    相关文章

      网友评论

          本文标题:006-小程序图片滑动、缩放加canvas打印

          本文链接:https://www.haomeiwen.com/subject/yvsdvftx.html