top
本文目录
单指拖拽
双指缩放
总结

微信小程序单指拖拽和双指缩放旋转

小程序单指拖拽和双指操作是一个比较常用的功能,效果如下图
在这里插入图片描述

  • 实现这三个功能,主要用三个触摸事件touchstarttouchmovetouchend
  • <view style="height: 100vh; width: 100vw">
    <image
    src="..."
    style="transform: translate({{translateX}}px, {{translateY}}px) scale({{scale}}) rotate({{rotate}}deg);"
    catch:touchstart="touchStart"
    catch:touchmove="touchMove"
    catch:touchend="touchEnd"
    />
    </view>
    <view style="height: 100vh; width: 100vw"> <image src="..." style="transform: translate({{translateX}}px, {{translateY}}px) scale({{scale}}) rotate({{rotate}}deg);" catch:touchstart="touchStart" catch:touchmove="touchMove" catch:touchend="touchEnd" /> </view>
    <view style="height: 100vh; width: 100vw">
      <image
        src="..."
        style="transform: translate({{translateX}}px, {{translateY}}px) scale({{scale}}) rotate({{rotate}}deg);"
        catch:touchstart="touchStart"
        catch:touchmove="touchMove"
        catch:touchend="touchEnd"
      />
    </view>
    
    • 用了以下变量
    • Page({
      data: {
      translateX: 0, // 位移x坐标 单位px
      translateY: 0, // 位移y坐标 单位px
      distance: 0, // 双指接触点距离
      scale: 1, // 缩放倍数
      rotate: 0, // 旋转角度
      oldRotate: 0, // 上一次旋转停止后的角度
      startMove: { // 起始位移距离
      x: 0,
      y: 0,
      },
      startTouches: [] // 起始点touch数组
      },
      })
      Page({ data: { translateX: 0, // 位移x坐标 单位px translateY: 0, // 位移y坐标 单位px distance: 0, // 双指接触点距离 scale: 1, // 缩放倍数 rotate: 0, // 旋转角度 oldRotate: 0, // 上一次旋转停止后的角度 startMove: { // 起始位移距离 x: 0, y: 0, }, startTouches: [] // 起始点touch数组 }, })
      Page({
        data: {
          translateX: 0, // 位移x坐标 单位px
          translateY: 0, // 位移y坐标 单位px
          distance: 0, // 双指接触点距离
          scale: 1, // 缩放倍数
          rotate: 0, // 旋转角度
          oldRotate: 0, // 上一次旋转停止后的角度
          startMove: { // 起始位移距离
            x: 0,
            y: 0,
          },
          startTouches: [] // 起始点touch数组
        },
      })
      

      单指拖拽

      • 单指拖拽比较简单,只需要记录移动的点坐标,然后减去起始点坐标,就可以求出针对页面的移动距离
      • touchstart
      • touchStart(e) {
        const touches = e.touches
        const { translateX, translateY } = this.data
        const { pageX, pageY } = touches[0]
        this.data.startMove = {
        x: pageX - translateX,
        y: pageY - translateY
        }
        this.data.startTouches = touches
        },
        touchStart(e) { const touches = e.touches const { translateX, translateY } = this.data const { pageX, pageY } = touches[0] this.data.startMove = { x: pageX - translateX, y: pageY - translateY } this.data.startTouches = touches },
        touchStart(e) {
          const touches = e.touches
          const { translateX, translateY } = this.data
          const { pageX, pageY } = touches[0]
          this.data.startMove = {
            x: pageX - translateX,
            y: pageY - translateY
          }
          this.data.startTouches = touches
        },
        
        • touchmove
        • touchMove(e) {
          const touches = e.touches
          const { pageX: onePageX, pageY: onePageY } = touches[0]
          const { startMove } = this.data
          this.setData({
          translateX: onePageX - startMove.x,
          translateY: onePageY - startMove.y
          })
          }
          touchMove(e) { const touches = e.touches const { pageX: onePageX, pageY: onePageY } = touches[0] const { startMove } = this.data this.setData({ translateX: onePageX - startMove.x, translateY: onePageY - startMove.y }) }
          touchMove(e) {
            const touches = e.touches
            const { pageX: onePageX, pageY: onePageY } = touches[0]
            const { startMove } = this.data
            this.setData({
              translateX: onePageX - startMove.x,
              translateY: onePageY - startMove.y
            })
          }
          

          双指缩放

          • 双指缩放的原理是根据两点坐标求出距离(勾股定理),然后在用移动坐标的距离比就可以求出缩放倍数
          • touchmove
      • touchMove(e) {
        const touches = e.touches
        const { pageX: onePageX, pageY: onePageY } = touches[0]
        const { startMove, scale, distance: oldDistance, startTouches } = this.data
        if (touches.length === 2 && startTouches.length === 2) {
        // 双指缩放
        const { pageX: twoPageX, pageY: twoPageY } = touches[1]
        // 求出当前双指距离
        const distance = Math.sqrt((twoPageX - onePageX) ** 2 + (twoPageY - onePageY) ** 2)
        this.data.distance = distance
        this.setData({
        scale: scale * (distance / (oldDistance || distance))
        })
        } else if (startTouches.length !== 2) {
        // 单指拖拽
        this.setData({
        translateX: onePageX - startMove.x,
        translateY: onePageY - startMove.y
        })
        }
        }
        touchMove(e) { const touches = e.touches const { pageX: onePageX, pageY: onePageY } = touches[0] const { startMove, scale, distance: oldDistance, startTouches } = this.data if (touches.length === 2 && startTouches.length === 2) { // 双指缩放 const { pageX: twoPageX, pageY: twoPageY } = touches[1] // 求出当前双指距离 const distance = Math.sqrt((twoPageX - onePageX) ** 2 + (twoPageY - onePageY) ** 2) this.data.distance = distance this.setData({ scale: scale * (distance / (oldDistance || distance)) }) } else if (startTouches.length !== 2) { // 单指拖拽 this.setData({ translateX: onePageX - startMove.x, translateY: onePageY - startMove.y }) } }
        touchMove(e) {
          const touches = e.touches
          const { pageX: onePageX, pageY: onePageY } = touches[0]
          const { startMove, scale, distance: oldDistance, startTouches } = this.data
          if (touches.length === 2 && startTouches.length === 2) {
          	// 双指缩放
            const { pageX: twoPageX, pageY: twoPageY } = touches[1]
            // 求出当前双指距离
            const distance = Math.sqrt((twoPageX - onePageX) ** 2 + (twoPageY - onePageY) ** 2)
            this.data.distance = distance
            this.setData({
              scale: scale * (distance / (oldDistance || distance))
            })
          } else if (startTouches.length !== 2) {
          	// 单指拖拽
            this.setData({
              translateX: onePageX - startMove.x,
              translateY: onePageY - startMove.y
            })
          }
        }
        

        startTouches.length !== 2这个判断的原因是防止图片跳动,因为如果你两个手指触摸,然后离开一个手指,我是禁止拖拽的,只有双指都离开后再次触摸才能单指拖拽
        双指旋转
        双指旋转的原理是根据三角函数求出起始点的角度,然后再求出移动坐标的角度,相减然后加上上一次旋转的角度就等于你当前所需的选择角度
        touchmove

        touchMove(e) {
        const touches = e.touches
        const { pageX: onePageX, pageY: onePageY } = touches[0]
        const { startMove, scale, distance: oldDistance, startTouches, oldRotate } = this.data
        if (touches.length === 2 && startTouches.length === 2) {
        const { pageX: twoPageX, pageY: twoPageY } = touches[1]
        const distance = Math.sqrt((twoPageX - onePageX) ** 2 + (twoPageY - onePageY) ** 2)
        + let rotate = this.getAngle(touches[0], touches[1]) - this.getAngle(startTouches[0], startTouches[1]) + oldRotate
        // 如果大于360度,就减去360
        + rotate = rotate > 360 ? rotate - 360 : rotate
        this.data.distance = distance
        this.setData({
        scale: scale * (distance / (oldDistance || distance)),
        + rotate
        })
        } else if (startTouches.length !== 2) {
        this.setData({
        translateX: onePageX - startMove.x,
        translateY: onePageY - startMove.y
        })
        }
        },
        touchMove(e) { const touches = e.touches const { pageX: onePageX, pageY: onePageY } = touches[0] const { startMove, scale, distance: oldDistance, startTouches, oldRotate } = this.data if (touches.length === 2 && startTouches.length === 2) { const { pageX: twoPageX, pageY: twoPageY } = touches[1] const distance = Math.sqrt((twoPageX - onePageX) ** 2 + (twoPageY - onePageY) ** 2) + let rotate = this.getAngle(touches[0], touches[1]) - this.getAngle(startTouches[0], startTouches[1]) + oldRotate // 如果大于360度,就减去360 + rotate = rotate > 360 ? rotate - 360 : rotate this.data.distance = distance this.setData({ scale: scale * (distance / (oldDistance || distance)), + rotate }) } else if (startTouches.length !== 2) { this.setData({ translateX: onePageX - startMove.x, translateY: onePageY - startMove.y }) } },
        touchMove(e) {
          const touches = e.touches
          const { pageX: onePageX, pageY: onePageY } = touches[0]
          const { startMove, scale, distance: oldDistance, startTouches, oldRotate } = this.data
          if (touches.length === 2 && startTouches.length === 2) {
            const { pageX: twoPageX, pageY: twoPageY } = touches[1]
            const distance = Math.sqrt((twoPageX - onePageX) ** 2 + (twoPageY - onePageY) ** 2)
        +   let rotate = this.getAngle(touches[0], touches[1]) - this.getAngle(startTouches[0], startTouches[1]) + oldRotate
            // 如果大于360度,就减去360
        +   rotate = rotate > 360 ? rotate - 360 : rotate
            this.data.distance = distance
            this.setData({
              scale: scale * (distance / (oldDistance || distance)),
        +     rotate
            })
          } else if (startTouches.length !== 2) {
            this.setData({
              translateX: onePageX - startMove.x,
              translateY: onePageY - startMove.y
            })
          }
        },
        
        
        • getAngle
        //getAngle
        getAngle(p1, p2) {
        const x = p1.pageX - p2.pageX
        const y = p1.pageY- p2.pageY
        return Math.atan2(y, x) * 180 / Math.PI
        }
        //getAngle getAngle(p1, p2) { const x = p1.pageX - p2.pageX const y = p1.pageY- p2.pageY return Math.atan2(y, x) * 180 / Math.PI }
        //getAngle
        getAngle(p1, p2) {
          const x = p1.pageX - p2.pageX
          const y = p1.pageY- p2.pageY
          return Math.atan2(y, x) * 180 / Math.PI
        }
        
        • touchend
        • touchEnd() {
          // 保存当前旋转角度
          this.data.oldRotate = this.data.rotate
          },
          touchEnd() { // 保存当前旋转角度 this.data.oldRotate = this.data.rotate },
          touchEnd() {
            // 保存当前旋转角度
            this.data.oldRotate = this.data.rotate
          },
          

          总结

          • 代码片段https://developers.weixin.qq.com/s/0nS1tImU7Rs5
          • H5原理一致,只需改一下语法即可
          • 我这个只是基础版本,如果需要一些边界控制和还一些需求的限制,计算据边框距离即可,也可以用小程序的boundingClientRectAPI
THE END
icon
0
icon
打赏
icon
分享
icon
二维码
icon
海报