微信小程序实现上下左右滑动触发联动选项卡绝对值事件parsestringifyMathatanabsfindIndex

Posted 牧码厂

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了微信小程序实现上下左右滑动触发联动选项卡绝对值事件parsestringifyMathatanabsfindIndex相关的知识,希望对你有一定的参考价值。

文章目录

序言

最近在写原生微信小程序项目的时候遇到了左右滑动内容更新数据,同时改变tabBar的高亮效果。于是就写了这篇文章,关于文章的css不再此文章中展示,因为都是公共的自定义类名css,所以通过类名大概就能推敲出css的值了。


1、html部分

<view class="font_size_36">
  <!-- tabBar选项卡 -->
  <view class="dis_r_c">
    <view class="grid_c3_230 grid_row_gap_10 grid_column_gap_10">
      <view class="border_777" wx:for="demoTabBar" wx:key="id">
        <view class="height_90 line_height_90 text_align_center isH===item.id?'color_royalblue':''" data-item="item" catchtap="catchtapTabBar">item.title</view>
      </view>
    </view>
  </view>

  <!-- 内容 -->
  <view class="margin_t_26 padding_b_36" bindtouchstart="slideStart" bindtouchmove="slideDirection" bindtouchend="slideEnd">
    <view>
      <view class="border_777 index!==0?'margin_t_16':''" wx:for="list" wx:key="id">
        <view class="ellipsis">item.title</view>
      </view>
    </view>
  </view>
</view>

2、javascript部分(上下左右滑动均触发)

第一步:在包裹内容的最外层HTML标签上定义滑动事件。如果页面同时存在横向滑动的选项卡,最好不要把滑动事件绑定到页面的最外层标签上。上下左右滑动均触发的功能只适合那种类似于看小说的页面,因为看小说要么往左滑,要么往右滑,要么往下滑,要么往上滑,要么斜着滑,页面上除了返回按钮,就没有其它复杂的功能了。所以适合这个上下左右滑动均触发的模式。
bindtouchstart="slideStart":开始滑动。
bindtouchmove="slideDirection":滑动事件,只要滑动就会触发。
bindtouchend="slideEnd":滑动结束,即手指离开屏幕时触发。
等号前面是微信小程序提供的绑定事件的属性,等号后面是自定义的事件名。

第二步:在全局引入页面结构数据,并解构。

第三步:data中的变量及其作用。
demoTabBar:选项卡数据。
originObjList:源数据对象,存放选项卡对应的所有数据内容。
isH:使用数据id设置选项卡的高亮值。
list:存储渲染列表的数据,也就是在切换选项卡时获取对应的数据值。
startX:开始滑动的X轴坐标值。
startY:开始滑动的Y轴坐标值。
direction:滑动方向,L向左滑,R向右滑。

第四步:页面初始化,定义一个名为init的函数,并在onLoad生命周期函数中调用init函数来实现页面初始化。在init函数中使用JSONparsestringify方法克隆数据,以保证数据的完全分离状态。接着便是初始化赋值,分别是tabBar赋值,originObjList数据源赋值,这个数据包含所有的tabBar类目的数据值;isH赋值,获取tabBar数据第一项的id值;list赋值,通过tabBar的第一项数据id获取newTabBar中对应的值。

第五步:绑定选项卡的点击事件,事件名称为catchtapTabBar。在选项卡标签上自定名为item的变量来向函数传递值。在函数中通过解构获取点击项的值,获取点击项中的id与源数据匹配选项卡的值,最后把得到的值和id值赋给data中的listisH两个变量。

第六步:绑定开始滑动事件,事件名称为slideStart。在函数中通过event获取开始滑动的clientXclientY的值。最后把值分别赋给data中的startXstartY,这个值也就是开始滑动的坐标值。

第七步:绑定滑动中的事件,事件名称为slideDirection。在函数中通过event获取实时滑动的坐标值,使用Math中的atanPI两个方法计算角度,通过角度的变化确定滑动的方向。Math.abs(angle) > 5050这个值如果越大,方向就越不容易被改变,值越大说明需要滑动更远的距离才能改变方向,同时把方向值赋给data中的direction变量等待滑动结束事件使用。

第八步:绑定滑动结束事件,定义事件名为slideEnd。在函数中准备好数据,首先判断方向,方向分别使用LR表示,也就是在滑动函数中改变的方向值。L表示向右滑相当于上一页,R表示向左滑相当于下一页。当方向值为L的时候需要i < tabBarLen - 1,当方向值为R的时候需要i > 0。其中tabBarLen - 1表示已经滑动到tabBar的最后一项,不能再向左滑动了。i > 0表示已经滑到tabBar的第一项,不能再向右滑动了。其中i的值通过findIndex方法和isH获取当前对应tabBar中的下标值,tabBarLen的值就是tabBar数据的长度。如果if判断成立,那么就获取对应的内容赋值给list,并且把isH的值同时更新为当前值。如果if条件不成立,那么就给datadriection变量赋值为空字符串。

const 
  globalData: 
    jsonData: 
      tabBar,
      objList
    ,
    showToast
  
 = getApp();

Page(

  /**
   * 页面的初始数据
   */
  data: 
    demoTabBar: [],
    originObjList: [],
    isH: '',
    list: [],
    startX: 0,
    startY: 0,
    direction: null
  ,
  
  // 滑动结束
  slideEnd() 
    let self = this,
      selfData = self.data,
      direction = selfData.direction,
      tabBar = selfData.demoTabBar,
      tabBarLen = tabBar.length,
      originObjList = selfData.originObjList,
      isH = selfData.isH,
      i = tabBar.findIndex(item => item.id === isH),
      id = '';

    if (direction === 'R' && i > 0)  // 向右滑相当于上一页
      i -= 1;
     else if (direction === 'L' && i < tabBarLen - 1)  // 向左滑相当于下一页
      i += 1;
     else  // 滑动不成立,清空driection
      return self.setData(
        direction: ''
      );
    
    
    id = tabBar[i].id;

    self.setData(
      list: originObjList[id],
      isH: id
    );
  ,

  // 滑动中判断滑动方向
  slideDirection( changedTouches ) 
    let self = this,
      selfData = self.data,
      // 开始x坐标
      startX = selfData.startX,
      // 开始y坐标
      startY = selfData.startY,
      // 活动变化坐标
      touchMoveX = changedTouches[0].clientX,
      // 滑动变化坐标
      touchMoveY = changedTouches[0].clientY,
      direction = '',
      _x = touchMoveX - startX,
      _Y = touchMoveY - startY,
      // Math.atan()返回数据的反正切值
      // 这里算的就是角度
      angle = 360 * Math.atan(_Y / _X) / (2 * Math.PI);

    // 滑动角度超过50retrun
    if (Math.abs(angle) > 50) return;

    if (touchMoveX > startX)  // 向右滑
      direction = 'R';
     else  // 向左滑
      direction = 'L';
    

    self.setData(
      direction
    );
  ,

  // 开始滑动 
  slideStart(e) 
    this.setData(
      startX: e.changedTouches[0].clientX,
      startY: e.changedTouches[0].clientY
    )
  ,
  
  // tabBar选项卡
  catchtapTabBar( currentTarget:  dataset:  item   ) 
    let self = this,
      selfData = self.data,
      originObjList = selfData.originObjList;

    self.setData(
      list: originObjList[item.id],
      isH: item.id
    );
  ,

  // 初始化
  init() 
    let newTabBar = JSON.parse(JSON.stringify(tabBar)),
      originObjList = JSON.parse(JSON.stringify(objList)),
      id = newTabBar[0].id;

    this.setData(
      demoTabBar: newTabBar,
      originObjList,
      isH: id,
      list: originObjList[id]
    );
  ,

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) 
    this.init();
  ,
)

3、JavaScript部分(左右滑动触发)

第一步:这步与上下左右滑动均触发案例的区别就是没有了滑动事件,因为不需要使用滑动事件。

第二步:这步与上下左右滑动均触发案例一样。

第三步:这步data中的变量与上下左右滑动均触发案例相比少了startXstartYdirection三个变量。同时增加了startPageX变量,这个变量用来记录滑动开始的pageX值,这次获取的不再是clientX的值。

第四步:页面初始化与上下左右滑动均触发案例相同。

第五步:绑定选项卡的点击事件与上下左右滑动均触发案例相同。

第六步:绑定开始滑动事件,事件名称为slideStart。在函数中通过event获取开始滑动的pageX值,通过parseInt方法舍弃小数部分(这步不是必须,只是个人偏好)。最终把值赋给data中的startPageX变量。

第七步:绑定滑动结束事件,定义事件名为slideEnd。在函数中准备好数据,itabBarLen变量值的获取和作用与上下左右滑动均触发案例相同,这里不再累赘解释。定义endPageXslidingDistancedirection三个变量,endPageX变量通过解构获取pageX赋值,也就是滑动结束的值,同样需要parseInt方法舍弃小数部分(这步不是必须,只是个人偏好)。slidingDistance变量存储endPageX(滑动结束值)和startPageX(滑动开始值)的差值。direction变量存储方向值,这个方向值是通过获取slidingDistance值的第一个字符决定,如果第一个字符是减号,说明向左滑动,否则向右滑动。if (Math.abs(slidingDistance) < 100) return false;通过Mathabs方法获取slidingDistance变量的绝对值与100比较,如果slidingDistance的值小于100,说明滑动距离太短,通过return中断函数,后续代码不再执行。如果slidingDistance的值大于100,后续代码继续执行,执行逻辑与上下左右滑动均触发案例的第八步类似。

const 
  globalData: 
    jsonData: 
      tabBar,
      objList
    ,
    showToast
  
 = getApp();

Page(

  /**
   * 页面的初始数据
   */
  data: 
    demoTabBar: [],
    originObjList: [],
    isH: '',
    list: [],
    startPageX: 0
  ,

  // 开始滑动 
  slideStart( changedTouches ) 
    let pageX = changedTouches[0].pageX;

    pageX = parseInt(pageX);

    this.setData(
      startPageX: pageX
    );
  ,

  // 滑动结束
  slideEnd( changedTouches ) 
    let self = this,
      selfData = self.data,
      endPageX = changedTouches[0].pageX,
      tabBar = selfData.demoTabBar,
      tabBarLen = tabBar.length,
      originObjList = selfData.originObjList,
      isH = selfData.isH,
      startPageX = selfData.startPageX,
      i = tabBar.findIndex(item => item.id === isH),
      id = '',
      slidingDistance = 0,
      direction = '';

    // 滑动结束,并舍弃小数点
    endPageX = parseInt(endPageX);
    // 滑动距离
    slidingDistance = endPageX - startPageX;
    // 滑动方向
    direction = String(slidingDistance)[0];

    if (!Math.abs(slidingDistance) > 100) return false;

    if (direction === '-' && i < tabBarLen - 1)  // 向左滑动
      i += 1;
     else if (direction !== '-' && i > 0)  // 向右滑动
      i -= 1;
     else 
      return false;
    

    id = tabBar[i].id;

    self.setData(
      list: originObjList[id],
      isH: id
    );
  ,

  // tabBar
  catchtapTabBar( currentTarget:  dataset:  item   ) 
    let self = this,
      selfData = self.data,
      originObjList = selfData.originObjList;

    self.setData(
      list: originObjList[item.id],
      isH: item.id
    );
  ,

  // 初始化
  init() 
    let newTabBar = JSON.parse(JSON.stringify(tabBar)),
      originObjList = JSON.parse(JSON.stringify(objList)),
      id = newTabBar[0].id;

    this.setData(
      demoTabBar: newTabBar,
      originObjList,
      isH: id,
      list: originObjList[id]
    );
  ,

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) 
    this.init();
  
)

4、效果演示

以上是关于微信小程序实现上下左右滑动触发联动选项卡绝对值事件parsestringifyMathatanabsfindIndex的主要内容,如果未能解决你的问题,请参考以下文章

微信小程序左右滑动切换页面事件

微信小程序——左右滑动切换页面

微信小程序实现左右联动的菜单列表

微信小程序直播消息滑动

小程序Swiper做Tab切换,带tab切换动画

微信小程序 子元素事件不触发父元素事件