微信小程序之小巧有趣的列表滑动效果

399 阅读3分钟

「这是我参与2022首次更文挑战的第5天,活动详情查看:2022首次更文挑战」。

前言

在开发小程序的时候遇到个小需求--某个页面里的某个列表,需要增加向左滑动展开修改和删除选项并且要带滑动的效果,我这想这不是简单么,小程序文档内应该有相应的组件,但是滑动组件受到限制,经过一顿操作小改了一下,效果图如下: image.png image.png

scroll-view组件的应用

可滚动视图区域:如果是上下滚动需要给它定义高度。 这边使用的是scroll-y左右滚动,如果是上下滚动则scroll-x。另外还有一个属性应用性比较多enable-back-to-top苹果和安卓端点顶部即可返回顶部,只支持上下滚动(可以做个参考)

<scroll-view scroll-y></scroll-view>

滚动视图渲染

渲染的列表肯定是不止一条数据,所以我这边先用循环遍历数组列表,使用block渲染多个结构块

<block wx:for="{{ list }}" wx:for-item="item" wx:for-index="index" wx:key="index">

手指触摸事件

bindtouchstartbindtouchmove分别是手指触摸事件和手机滑动事件,通过事件监听可以进行判断,达到目的

<view class="list {{ item.isTouchMove ? 'touch-move-active' : '' }}" bindtouchstart="touchStart" bindtouchmove="touchMove" data-index="{{ index }}">

手指触摸开始

开始触摸时,操作当前触摸的模块回到滚动之前的位置,设置transform: translateX(0);,重置完成后记录手指触摸滑动的坐标 e.changedTouches[0].clientXe.changedTouches[0].clientY

  touchStart: function (e) {
    let that = this;
    that.data.list.forEach(function (v, i) {
      if (v.isTouchMove) v.isTouchMove = false; // 只操作为true的
    })
    that.setData({
      startX: e.changedTouches[0].clientX, // 开始X坐标
      startY: e.changedTouches[0].clientY, // 开始Y坐标
      warningList: that.data.warningList
    })
  },

手指触摸后

touchMove回调函数内event参数获取当前滑动的下标

touchMove: function (e) {
    index = e.currentTarget.dataset.index, 
}

获取开始x,y坐标系

var startX = that.data.startX,
var startY = that.data.startY,

滑动变化的x,y坐标系,通过changedTouches属性获取

var touchMoveX = e.changedTouches[0].clientX
var touchMoveY = e.changedTouches[0].clientY

计算滑动的角度,封装了一个方法,公式:360 * Math.atan(_Y / _X) / (2 * Math.PI);

  angle: function (start, end) {
    let that = this,
      _X = end.X - start.X,
      _Y = end.Y - start.Y;
    // 返回角度 /Math.atan()返回数字的反正切值
    return 360 * Math.atan(Y / X) / (2 * Math.PI);
  },

获取滑动角度,分别传入X,Y轴坐标和滑动变化的X,Y坐标

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

判断滑动角度,遍历当前列表数组,设置isTouchMovefalse,表示已经滑动。 如果是滑动超过30度角,则return停止,Math.abs方法判断,如果滑动坐标超过当前坐标则为右滑动,否则为左滑。

that.data.list.forEach(function (v, i) {
  v.isTouchMove = false
  if (Math.abs(angle) > 30) return;
  if (i == index) {
    // 右滑
    if (touchMoveX > startX)
      v.isTouchMove = false
    // 左滑
    else
      v.isTouchMove = true
  }
})

最后更新数据

this.setData({
 list: that.data.warningList
})

滑动样式

滑动内容在渲染view内和渲染内容同级展示,用display:false分到两边,两个按钮大小分别为120rpx

<view class="scrollText">
    <view class="edit" bindtap="editList" data-groupid="{{item.id}}"> 修改 </view>
    <view class="del" bindtap="delList" data-groupid="{{item.id}}"> 删除 </view>
</view>

列表展示数据宽度设置为100%,否则会把删除修改按钮露出来,margin-left向左偏移240rpx,这样就彻底通过滑动来控制

  width: 100%;
  display: flex;
  padding:20rpx;
  justify-content: space-between;
  margin-left: -240rpx;
  background-color: #fff;
  flex-direction: column;

分别给展示的数据和修改删除按钮设置滑动方向,使其达到一致

-webkit-transform: translateX(0);
transform: translateX(0);

滑动动画效果和和偏移量,translateX也是为240rpx,也就是两个按钮的长度,否则不能全部把按钮展示出来。transition0.4s时长

  transform: translateX(240rpx);
  transition: all 0.4s;