美文网首页
微信小程序实现tap切换(可手势滑动、导航跟随滚动)

微信小程序实现tap切换(可手势滑动、导航跟随滚动)

作者: Zzc皮卡丘 | 来源:发表于2020-04-24 18:39 被阅读0次
    demo效果.gif

    开篇

    直接说重点,本篇内容主要实现的功能有:导航栏tap切换、导航栏跟随滚动居中显示、手势滑动切换。
    目前网上能看的讲解的多多少少有些问题,功能不够完整,走了很多弯路才调整成比较稳定效果和体验,开发过程中也借用了一些别人的案例。下面页面实现代码全部贴上,可直接copy套用。

     

    1、js实现

    js这部分\color{rgb(255,0,0)}{特别强调}页面触摸事件,通过触摸判断手势滑动的方向,重点在\color{rgb(255,0,0)}{获取手势触摸XY轴坐标}位置。

    list页面不需要上下滚动,固定一屏的大小,只有左右滑动请使用:
    this.starthDotX = e.touches[0].pageX;
    this.starthDotY = e.touches[0].pageY;

    list页面需要上下滚动,类似scroll-view效果,需上下左右滚动请使用:
    如果list页面需要滚动,使用e.touches[0].pageX方法。list页面会上下滚动到某一个点的时候XY轴数据与实际滑动距离不符合,导致判断方法失效,上下滑动的同时突然执行左右滑动的操作,滑动的时候乱窜的情况
    this.starthDotX = e.touches[0].clientX;
    this.starthDotY = e.touches[0].clientY;

    判断触摸手势方向的逻辑:
    if(Math.abs(X) > Math.abs(Y) && X > 0 && Math.abs(X) > minOffset) {
    console.log("向右滑动");
    }else if(Math.abs(X) > Math.abs(Y) && X < 0 && Math.abs(X) > minOffset) {
    console.log("向左滑动");
    }else if(Math.abs(X) < Math.abs(Y) && Y > 0) {
    console.log("向下滑动");
    }else if(Math.abs(X) < Math.abs(Y) && Y < 0) {
    console.log("向上滑动");
    }

    上代码:

    var minOffset = 30;//最小偏移量,低于这个值不响应滑动处理
    
    var DtaList0 = [{Name: "锦绣未央", url:"/image/timg0.jpg"},{Name: "锦民国往事", url:"/image/timg0.jpg"},{Name: "陈情令", url:"/image/timg0.jpg"}];
    var DtaList1 = [{url:"/image/timg1.jpg", Name: "笑傲江湖"},{url:"/image/timg1.jpg", Name: "绣春刀"},{url:"/image/timg1.jpg", Name: "白夜追凶"},{url:"/image/timg1.jpg", Name: "三生三世"}];
    var DtaList2 = [{url:"/image/timg2.jpg", Name: "法证先锋"},{url:"/image/timg2.jpg", Name: "无心法师"},{url:"/image/timg2.jpg", Name: "我是余欢水"}];
    var DtaList3 = [{url:"/image/timg3.jpg", Name: "东宫"},{url:"/image/timg3.jpg", Name: "我只喜欢你"},{url:"/image/timg3.jpg", Name: "我只喜欢你"},{url:"/image/timg3.jpg", Name: "爱情公寓"}];
    var DtaList4 = [{url:"/image/timg4.jpg", Name: "刘老根3"},{url:"/image/timg4.jpg", Name: "镇魂街"},{url:"/image/timg4.jpg", Name: "仙剑奇侠3"},{url:"/image/timg4.jpg", Name: "寻情记"}];
    var DtaList5 = [{url:"/image/timg5.jpg", Name: "人民的正义"},{url:"/image/timg5.jpg", Name: "亮剑"}];
    var DtaList6 = [{url:"/image/timg6.jpg", Name: "楚汉传奇"},{url:"/image/timg6.jpg",Name: "少帅"},{url:"/image/timg6.jpg",Name: "步步惊心"}];
    var DtaList7 = [{url:"/image/timg7.jpg", Name: "大唐女法医"},{url:"/image/timg7.jpg", Name: "十二传说"}];
    var DtaList8 = [{url:"/image/timg8.jpg", Name: "甄嬛传"},{url:"/image/timg8.jpg", Name: "萧十一郎"},{url:"/image/timg8.jpg", Name: "开国大典"}];
    var DtaListArray = [DtaList0, DtaList1, DtaList2, DtaList3, DtaList4, DtaList5, DtaList6, DtaList7]
    
    Page({
      /*
       * 页面的初始数据
       */
      data: {
        DtaList: [{}], //存放每个页面list数据
        activeId: "", //记录导航栏tap的id
        tabIndex: 0,//记录导航栏点击位置
        starthDotX : 0, //触摸事件开始X轴的位置
        starthDotY : 0,//触摸事件开始Y轴的位置
    
        TypeList: [{posterId: 10561005, typeDesc: "央视网"},{posterId: 10561003, typeDesc: "爱奇艺"},{posterId: 10561008, typeDesc: "腾讯视频"},{posterId: 10561010, typeDesc: "PPTV"},{posterId: 10561002, typeDesc: "优酷"},{posterId: 10561007, typeDesc: "哔哩哔哩"}, {posterId: 10561006, typeDesc: "芒果TV"}, {posterId: 10561004, typeDesc: "西瓜视频"}]   //导航栏假数据
      },
    
    /*****************************tap切换点击事件*****************************/
      changeTab: function (e) {
        var id = e.target.dataset.type;
        var index = e.target.dataset.index;
    
        //禁止tap重复点击
        if(index == this.data.tabIndex){
          return
        }
    
        //改变tap点击位置
        this.setData({
          activeId: id,
          tabIndex:index, 
          DtaList: DtaListArray[index]
        });
    
        //当前tab点击栏居中显示
        var singleNavWidth = this.data.windowWidth / 5;
        this.setData({
          navScrollLeft: (index - 2) * singleNavWidth
        }) 
      },
    
      /*****************************触摸事件*****************************/
      //触摸开始
      touchstart: function(e){
        // this.starthDotX = e.touches[0].pageX;
        // this.starthDotY = e.touches[0].pageY;
        this.starthDotX = e.touches[0].clientX;
        this.starthDotY = e.touches[0].clientY;
      },
        
      //触摸进行中
      touchmove: function(e){
        var Direction = ""
        // var moveDotX = e.touches[0].pageX;
        // var moveDotY = e.touches[0].pageY;
        var moveDotX = e.touches[0].clientX;
        var moveDotY = e.touches[0].clientY;
        
        var X = moveDotX - this.starthDotX;
        var Y = moveDotY - this.starthDotY;
    
        if(Math.abs(X) > Math.abs(Y) && X > 0 && Math.abs(X) > minOffset) {
          Direction = "右滑"
        }else if(Math.abs(X) > Math.abs(Y) && X < 0 && Math.abs(X) > minOffset) {
          Direction = "左滑"
        }else if(Math.abs(X) < Math.abs(Y) && Y > 0) {
          Direction = "下滑"
        }else if(Math.abs(X) < Math.abs(Y) && Y < 0) {
          Direction = "上滑"
        } 
    
        //记录当前滑动方向
        this.setData({
          glideDirection: Direction 
        })
      },
    
      //触摸结束
      touchend: function(e){
        if(this.data.glideDirection == "右滑"){
          if(this.data.tabIndex !== 0){
            var typeData = this.data.TypeList[this.data.tabIndex - 1];
            var posterId = typeData.posterId;
    
            //改变tap点击位置
            this.setData({
              activeId: posterId,
              tabIndex: this.data.tabIndex - 1,
              DtaList: DtaListArray[this.data.tabIndex - 1]
            })
    
            //新增tab点击当前栏居中显示
            var singleNavWidth = this.data.windowWidth / 5;
            this.setData({
               navScrollLeft: (this.data.tabIndex - 2) * singleNavWidth
            }) 
          }else{
            console.log("我是第一个滑不动啦,不要滑啦!!!")
          }
        }else if(this.data.glideDirection == "左滑"){
          if(this.data.tabIndex !== this.data.TypeList.length -1){
            var typeData = this.data.TypeList[this.data.tabIndex + 1];
            var posterId = typeData.posterId;
            //改变tap点击位置
            this.setData({
              activeId: posterId,
              tabIndex: this.data.tabIndex + 1,
              DtaList: DtaListArray[this.data.tabIndex + 1]
            })
    
            //tab点击当前栏居中显示
            var singleNavWidth = this.data.windowWidth / 5;
            this.setData({
               navScrollLeft: (this.data.tabIndex - 2) * singleNavWidth
            }) 
          }else{
            console.log("已经是最后一个啦,不要滑啦!!!")
          }
        }
      },
    
    
      //列表cell点击事件
      clickBrand: function (e) {
        var index = e.currentTarget.id;
        var listData = this.data.DtaList[index];
        console.log("当前点击的是:" + listData.Name)
      },
    
      /**
       * 生命周期函数--监听页面加载
       */
      onLoad: function (options) {
        //改变tap点击位置
        this.setData({
          activeId: '10561005',
          DtaList: DtaList0
        });
        
        //新增获取屏幕Width
        wx.getSystemInfo({
          success: (res) => {
              this.setData({
                  windowWidth: res.windowWidth
              })
          },
        })       
      },
    
      /**
       * 生命周期函数--监听页面初次渲染完成
       */
      onReady: function () {
        
      },
      
      /**
       * 生命周期函数--监听页面显示
       */
      onShow: function () {//页面已经显示出来
        
      }
    })
    

     

    2、wxml实现

    这部分没有太多难度,跟搭积木一样,一个view一个view的嵌套。

    导航栏部分
    原理:通过<scroll-view>控件实现,for循环每一个按钮,实现点击/滑动切换。
    控件属性:scroll-left="{{navScrollLeft}} -> 用来控制当前点击栏滚动的位置,滚动居中效果。

    list列表部分
    原理:没有使用系统swiper组件,而是通过for循环<view>的形式实现。
    控件属性:bindtouchstart="touchstart" / bindtouchmove="touchmove"/ bindtouchend="touchend" -> 监听list页面的触摸动作

    上代码:

    <scroll-view scroll-x="true" class="ip_tab_comtainer" scroll-with-animation="{{true}}" scroll-left="{{navScrollLeft}}">
      <block wx:for="{{TypeList}}" wx:for-item="item" wx:ky = "*this" wx:for-index = "index">
        <view class="ip_tab_item_n {{activeId == item.posterId?'active':''}}" bindtap="changeTab" data-type="{{item.posterId}}" data-index="{{index}}">{{item.typeDesc}}
        </view>
      </block>
    </scroll-view>
    
    <view class = "hotView" bindtouchstart="touchstart" bindtouchmove="touchmove" bindtouchend="touchend">
        <view class = "hotCell" wx:for = "{{DtaList}}"  wx:for-item='item' wx:for-index="dindex" wx:ky = "*this" bindtap = "clickBrand" id = "{{dindex}}">
            <view class='imageBottomView'>
              <image src="{{item.url}}"></image>
            </view>
            <view class='textBottom'>
              <view class ="title" style="opacity:{{1}}">{{item.Name}}</view>
            </view>
        </view>
    </view>
    
    

     

    3、wxss实现

    这部分没有太多可说的,样式自己慢慢去调。

    上代码:

    page{
      background-color: #F1F1F1; 
    }
    
    ::-webkit-scrollbar{/*隐藏scrollerView滚动条*/
        width: 0;
        height: 0;
        color: transparent;
    }
    
    .ip_tab_comtainer {
      width: 100%;
      display: flex;
      position:fixed;
      margin-bottom: 6rpx;
      white-space: nowrap;
      background-color: #ffffff;
    }
    
    .ip_tab_item_n {
      display: inline-block;
      margin: 0rpx 25rpx 0rpx 25rpx;
      padding: 28rpx 0rpx 20rpx 0rpx;
      color: #666666;
      font-size: 32rpx;
      text-align: center;
      overflow: hidden;
      text-overflow: ellipsis;
    }
    
    .active{
      color: #F7353B;
      border-bottom: 6rpx solid #F7353B; 
    }
    
    .hotView {
      display: flex;
      flex-wrap: wrap;
      padding-top: 120rpx;
    }
    
    .hotView .hotCell {
      width: 46%;
      text-align: center;
      margin-bottom: 20rpx;
      margin-left: 15rpx;
      margin-right: 15rpx;
    }
    
    .imageBottomView{
      width: 100%;
      height: 450rpx;
    }
    
    .imageBottomView image{
      width: 100%;
      height: 100%;
      border-radius: 5px 5px 0px 0px;
    }
    
    
    .textBottom{
      height: 65rpx;
      display: flex;
      align-items: center;
      background-color: white;
      border-radius: 0px 0px 5px 5px;
    }
    .textBottom .title{
      width: 65%;
      color: #5E5E5E;
      text-align: left;
      font-size: 30rpx;
    }
    
    

    如有不足欢迎留言一起补充探讨 ~

    相关文章

      网友评论

          本文标题:微信小程序实现tap切换(可手势滑动、导航跟随滚动)

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