微信小程序 仿 SwipeCell 的滑动单元格 SwipeBox

效果

请添加图片描述

代码

页面

调用Page

<block wx:for="{
     
     {4}}" wx:key="{
     
     {item}}">
    <view style="text-align:center;padding:20px">
       <swipe-box>
          <view slot="left" style="">
                    左侧内容
          </view>
             <view class="center" 
             style="height:100px;width:200px;background:#f4f4f4">
                    中间内容
                </view>
                <view slot="right" style="">
                    右侧内容
                </view>
            </swipe-box>
        </view>
</block>

SwipeBox wxml

<view class="swipe-box"
      bindtouchstart="touchstartHandle"
      bindtouchmove="touchmoveHandle">
    <view class="content {
     
     {direction}}"
          style="--left--:{ 
        { 
        -leftCellWidth}}px;--right--:{ 
        { 
        rightCellWidth}}px">
        <view class="left-handle">
            <slot name="left"/>
        </view>
        <slot/>
        <view class="right-handle">
            <slot name="right"/>
        </view>
    </view>
</view>

SwipeBox wxss

.swipe-box {
    
    
    overflow: hidden;
    display: inline-block;
}

.swipe-box > .content {
    
    
    position: relative;
    display: inline-block;
    transition: transform .3s;
}

.left-handle {
    
    
    position: absolute;
    right: 100%;
    top: 0;
    height: 100%;
    width: 150px;
    background: #f3f4fd;
}

.content {
    
    
    display: inline-block;
}

.right-handle {
    
    
    position: absolute;
    left: 100%;
    top: 0;
    height: 100%;
    width: 150px;
    background: #ddd;
}

.swipe-box > .content.left {
    
    
    transform: translateX(var(--left--))
}

.swipe-box > .content.right {
    
    
    transform: translateX(var(--right--))
}

SwipeBox js

const DISTANCE = 50
Component({
    
    
  options: {
    
    
    addGlobalClass: true,
    virtualHost: true,
    multipleSlots: true
  },
  externalClasses: ['custom-class'],
  data: {
    
    
    direction: '',
    leftCellWidth: 0,
    rightCellWidth: 0,
  },
  lifetimes: {
    
    
    ready() {
    
    
      const vm = this
      vm.uuid = wx.guid()
      //获取左右插槽元素宽度
      vm.createSelectorQuery().selectAll('.left-handle,.right-handle').boundingClientRect(rects => {
    
    
        vm.setData({
    
    
          leftCellWidth: rects[0].width,
          rightCellWidth: rects[1].width
        })
      }).exec()

      wx.RE.on('swipe-move', (uuid) => {
    
    
        if (vm.uuid != uuid) {
    
    
          vm.setData({
    
     direction: '' })
        }
      })
      vm.startX = 0
      vm.startY = 0
      vm.handleLock = true
    }
  },
  methods: {
    
    
    touchstartHandle(e) {
    
    
      //每次开始先解锁
      this.handleLock = false
      this.startX = e.changedTouches[0].clientX
      this.startY = e.changedTouches[0].clientY
    },
    touchmoveHandle(e) {
    
    
      if (this.handleLock) {
    
    
        return
      }
      const vm = this
      let {
    
     startX, startY } = vm;
      let slidingRange = 45; //
      let touchMoveX = e.changedTouches[0].clientX;
      let touchMoveY = e.changedTouches[0].clientY;

      //当任意方向移动距离大于阈值后判定滑动完成
      if (Math.abs(touchMoveX - startX) >= DISTANCE || Math.abs(touchMoveY - startY) >= DISTANCE) {
    
    
        vm.handleLock = true

        let angle = vm.angle({
    
     X: startX, Y: startY }, {
    
     X: touchMoveX, Y: touchMoveY });

        let direction = '', oldDirection = vm.data.direction
        //为了方便计算取绝对值判断
        if (Math.abs(angle) > slidingRange && touchMoveY < startY) {
    
    
          // 向上滑动
          direction = oldDirection === 'down' ? '' : 'up'
        }
        if (Math.abs(angle) > slidingRange && touchMoveY > startY) {
    
    
          // 向下滑动
          direction = oldDirection === 'up' ? '' : 'down'
        }
        if (Math.abs(angle) < 45 && touchMoveX < startX) {
    
    
          // 向左滑动
          direction = oldDirection === 'right' ? '' : 'left'
        }
        if (Math.abs(angle) < 45 && touchMoveX > startX) {
    
    
          // 向右滑动
          direction = oldDirection === 'left' ? '' : 'right'
        }
        vm.setData({
    
     direction })
        wx.RE.emit('swipe-move', vm.uuid)
      }
    },
    //计算滑动角度 start 起点坐标 end 终点坐标
    angle(start, end) {
    
    
      //返回角度 Math.atan()返回数字的反正切值
      return 360 * Math.atan((end.Y - start.Y) / (end.X - start.X)) / (2 * Math.PI);
    }
  }
})

备注

代码中出现的如下内容可自行实现
wx.RE 为全局事件管理,用于管理SwipeBox 之间以及与其他内容的交互
guid() 自定义唯一索引函数

参考

滑动方向判断

猜你喜欢

转载自blog.csdn.net/weixin_43954962/article/details/126040140