vue tab自动切换居中显示

vue组件 yekong

需求

在Vue项目开发中,有时我们需要实现一个Tab菜单,当点击某个Tab时,该Tab能够自动居中显示。本文将介绍如何使用Vue和BetterScroll库实现这一功能。

vue tab自动切换居中显示

动态效果

代码实现

以下是完整的代码实现,包括模板、脚本和样式部分。

模板部分

<template>
  <div class="menu-list">
    <div class="menu-list-inner horizontal-scrollbar-container">
      <div class="tabs-menus scroll-wrapper" ref="scroll">
        <div class="scroll-content" ref="scroll2">
          <div class="tabs">
            <div
                class="tab-item"
                @click="scrollToCenter(index)"
                :class="{ active: activeIndex === index }"
                ref="scrollItem"
                v-for="(item, index) in list"
                :key="index"
            >
              <span>{{ item.title }}</span>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

脚本部分

<script>
import BScroll from '@better-scroll/core'

export default {
  name: "MenuList",
  data() {
    return {
      list: [
        {title: '刑事侦查中心1', id: 0},
        {title: '融合作战中心2', id: 1},
        {title: '技术侦查中心3', id: 2},
        {title: '警务智援中心4', id: 3},
        {title: '刑事侦查中心5', id: 4},
        {title: '融合作战中心6', id: 5},
        {title: '技术侦查中心7', id: 6},
        {title: '警务智援中心8', id: 7},
      ],
      activeIndex: 0 // 默认选中第一个
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.scrollInit();
      setTimeout(() => {
        const currentPath = this.$route.path;
        console.log(currentPath)
        const currentIndex = this.list.findIndex(item => item.link === currentPath);
        if (currentIndex !== -1) {
          this.scrollToCenter(currentIndex);
        }
      }, 1000)
    });
  },
  methods: {
    scrollToCenter(index) {
      this.activeIndex = index; // 更新选中的索引
      this.$nextTick(() => {
        const scrollItems = this.$refs.scrollItem;
        if (scrollItems && scrollItems.length > index) {
          const targetElement = scrollItems[index];
          const scrollContainerRect = this.$refs.scroll.getBoundingClientRect();
          const targetElementRect = targetElement.getBoundingClientRect();
          let offsetX = targetElementRect.left + targetElementRect.width / 2 - scrollContainerRect.left - scrollContainerRect.width / 2;
          let targetX = this.scroll.x - offsetX;
          const maxScrollX = this.scroll.maxScrollX;

          // 如果选中的是最后一个元素,则保持在最右侧
          if (index === this.list.length - 1) {
            targetX = maxScrollX;
          } else {
            targetX = Math.max(targetX, maxScrollX);
            targetX = Math.min(targetX, 0);
          }

          this.scroll.scrollTo(targetX, 0, 500);
        }
      });
    },
    scrollInit() {
      this.scroll = new BScroll(this.$refs.scroll, {
        scrollX: true,
        scrollY: false,
        click: true,
        bounce: true,
        probeType: 1,
        scrollbar: {
          fade: false,
          interactive: false,
          scrollbarTrackClickable: false,
          scrollbarTrackOffsetType: 'clickedPoint'
        }
      });
      this.scroll.on('scrollEnd', (e) => {
        console.log('scrollEnd')
        this.lastSpot = Math.abs(e.x)
      });
      this.scroll.on('scrollStart', (e) => {
        console.log('scrollStart')
        console.log(e)
      });
      this.scroll.on('scroll', () => {
        console.log('scroll')
      });
    }
  }
}
</script>

样式部分

<style scoped lang="scss">
.menu-list {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: nowrap;
  flex-direction: row;
  position: relative;
  width: calc(100% - 40px);
  margin-left: 20px;
  height: 60px;
}

.menu-list-inner {
  width: 100%;
  overflow: hidden;
  position: relative;
  height: calc(100% - 10px);
}

.tabs {
  display: flex;
  padding: 0;
  margin-top: 5px;
  position: relative;
  height: calc(100% - 10px);
  width: calc(100% - 70px);
  overflow: hidden;
}

.tab-item {
  position: relative;
  height: 34px;
  width: 134px;
  margin-right: 10px;
  display: flex;
  justify-content: center;
  align-items: center;
  cursor: pointer;
  flex-wrap: nowrap;
  flex-direction: row;
  align-content: flex-start;
  background: url("./assets/tabg1.png") no-repeat;
  background-size: 100% 100%;
  opacity: 0.7;
}

.tab-item.active {
  opacity: 1;
}

.tabs-menus {
  display: flex;
  padding: 0;
  position: relative;
  height: 100%;
}

.scroll-content {
  display: inline-block;
  align-self: center;
  position: relative;
  height: 100%;
}
</style>

代码解析

  1. 模板部分:使用了v-for指令遍历list数组生成Tab项,并绑定点击事件scrollToCenter,点击时会将对应的Tab居中显示。
  2. 脚本部分
    • data:定义了list数组和activeIndexlist数组存储了Tab项的数据,activeIndex存储当前选中的Tab索引。
    • mounted:在组件挂载后初始化滚动,并根据当前路由路径设置默认选中的Tab。
    • methods:定义了scrollToCenter方法,用于将选中的Tab居中显示;scrollInit方法用于初始化BetterScroll。
  3. 样式部分:定义了各个元素的样式,确保Tab项能够正确显示和居中。

到这里我们就实现上面动态切换的效果了,接下来我们继续完善,让效果稍微酷炫一些,我们给选中的元素增加一个流光效果。

增加流光效果

之前选中的效果看起来不够明显,我们处理一下让其更加明显酷炫一些。这里我们使用ae来制作帧动画,然后渲染到页面中。

增加扫光效果

除了上面的流光效果,我们也可以制作扫光效果

ae源文件

ae源文件

vue tab自动切换居中显示源文件下载

源文件包括 ae动画源文件

vue3 vite js框架源文件

相关文件下载地址
此资源需支付 ¥2 后下载
支付宝购买扫右侧红包码购买更优惠,如无法下载请联系微信:17331886870
喜欢
vue tab自动切换居中显示