欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

原生微信小程序,navigate(导航栏)tab栏,tab栏与swiper结合,含过渡动画,初级

程序员文章站 2024-03-21 11:31:16
...

原生微信小程序,navigate(导航栏)tab栏,tab栏与swiper结合,含过渡动画,初级

看一下演示效果

原生微信小程序,navigate(导航栏)tab栏,tab栏与swiper结合,含过渡动画,初级

之前也做过一个类似的,tab(navigator) 栏,但是 tab 标签下面的小横线没有过渡效果,看起来会很生硬,而且不是和 swiper 联动,总体效果不尽人意,这是一个改进版

之前的 tab 栏切换效果演示,用来做学习的话还是很不错的,感兴趣的可以点这里跳转->旧版(学习版)地址

原生微信小程序,navigate(导航栏)tab栏,tab栏与swiper结合,含过渡动画,初级
看一下代码吧,实现起来比较简单,也比较初级
.wxml

<!-- tab -->
<view class="tit_box">
	<view class='navbar' id="navbar">
		<!-- 循环遍历导航栏 -->
		<!-- 保留关键字 *this 代表在 for 循环中的 item 本身,这种表示需要 item 本身是一个唯一的字符串或者数字。 -->
		<block wx:for="{{tabs}}" wx:key="*this">
			<view class="navbar-item" data-index='{{item.id}}' bindtap='onTabClick'>
				<view class="navbar-title {{item.isActive?'active':''}}">{{item.name}}</view>
			</view>
		</block>
		<!-- 导航栏下部的小横线 -->
		<view class="navbar-slider" style="left: {{sliderLeft}}px; width:50px; transition: all .5s;);" />
	</view>
</view>
<!-- 内容区  swiper -->
<swiper current="{{swiperCurrent}}" circular bindchange='swiperChange'>
	<swiper-item wx:for="{{tabs}}" wx:key="*this">
		<view class="content">{{item.name}}</view>
	</swiper-item>
</swiper>

.wxss( 这次没用less,感兴趣的同学可以自己改一下,样式啥的基本没啥特别难的 )

.tit_box {
    display: flex;
}

.navbar {
    display: flex;
    position: relative;
    flex: 1;
    z-index: 500;
    top: 0;
    width: 100%;
    background-color: #ececec;
}

.navbar .navbar-item {
    position: relative;
    display: block;
    flex: 1;
    padding: 13px 0;
    text-align: center;
    font-size: 0;
}


.navbar .navbar-title {
    display: inline-block;
    font-size: 15px;
    width: auto;
}

.active {
    color: #118ef5;
}

.navbar .navbar-slider {
    position: absolute;
    content: " ";
    left: 0;
    bottom: 0;
    width: 100rpx;
    height: 5rpx;
    background-color: #118ef5;
}

.content {
    background-color: rgb(0, 255, 85);
    height: 100%;
    text-align: center;
}

.js

let itemWidth = 0;
Page({
  data: {
    // 每个tab位置下的小横线坐标,每次切换后的坐标记录在数组中
    sliderOffsets: [],
    // tab下面的横线,偏左的距离
    sliderLeft: 0,
    tabs: [
      {
        id: 0,
        name: "TAB1",
        isActive: true
      },
      {
        id: 1,
        name: "TAB2",
        isActive: false
      },
      {
        id: 2,
        name: "TAB3",
        isActive: false
      }
    ],
    swiperCurrent: 0
  },
  onLoad: function (options) {
    this.clueOffset();
  },
  clueOffset() {
    // 保留外部的this
    var that = this;
    //声明节点查询的方法
    wx.createSelectorQuery().select('#navbar')
      .boundingClientRect(function (rect) {
        // Math.ceil向上取整,itemWidth(每个tab的宽度--距离) = tab栏宽度(375px) / tab数量(3)
        itemWidth = Math.ceil(rect.width / that.data.tabs.length);
        // 定义一个空数组,接收每个tab位置下的小横线坐标
        let tempArr = [];
        // 几个tab循环几次,把坐标填进去
        for (let i in that.data.tabs) {
          // -50是因为下面的小横线宽度是50
          tempArr.push((itemWidth * i) + ((itemWidth - 50) / 2));
        }
        that.setData({
          sliderOffsets: tempArr,
          sliderLeft: tempArr[0]
        });
      }).exec();
  },
  /**
   * tabItme点击事件
   */
  onTabClick(event) {
    // 获取点击的tabItme序号
    let { index } = event.currentTarget.dataset;
    this.forEachChange(index)
    this.setData({
      sliderLeft: this.data.sliderOffsets[index],
      swiperCurrent: index
    })
  },
  /**
   * swiper-item切换时执行的函数
   */
  swiperChange: function (e) {
    // 获取当前swiper-item的序号
    const { current } = e.detail
    this.forEachChange(current)
    this.setData({
      sliderLeft: this.data.sliderOffsets[current],
      swiperCurrent: current
    })
  },
  /**
   * 提取公共部分,封装成函数(tab标签选中的颜色)
   */
  forEachChange: function (index) {
    const { tabs } = this.data;
    tabs.forEach((v, i) => i === index ? v.isActive = true : v.isActive = false)
    this.setData({
      tabs
    })
  }
})

代码gitee地址:https://gitee.com/chenminghuisir/wechat-applet-component
也可以点击这里直接跳转
代码保存在仓库,PrincessConnect文件里