需求
在Vue项目开发中,有时我们需要实现一个Tab菜单,当点击某个Tab时,该Tab能够自动居中显示。本文将介绍如何使用Vue和BetterScroll库实现这一功能。
动态效果
代码实现
以下是完整的代码实现,包括模板、脚本和样式部分。
模板部分
<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>
代码解析
- 模板部分:使用了
v-for
指令遍历list
数组生成Tab项,并绑定点击事件scrollToCenter
,点击时会将对应的Tab居中显示。 - 脚本部分:
data
:定义了list
数组和activeIndex
,list
数组存储了Tab项的数据,activeIndex
存储当前选中的Tab索引。mounted
:在组件挂载后初始化滚动,并根据当前路由路径设置默认选中的Tab。methods
:定义了scrollToCenter
方法,用于将选中的Tab居中显示;scrollInit
方法用于初始化BetterScroll。
- 样式部分:定义了各个元素的样式,确保Tab项能够正确显示和居中。
到这里我们就实现上面动态切换的效果了,接下来我们继续完善,让效果稍微酷炫一些,我们给选中的元素增加一个流光效果。
增加流光效果
之前选中的效果看起来不够明显,我们处理一下让其更加明显酷炫一些。这里我们使用ae来制作帧动画,然后渲染到页面中。
增加扫光效果
除了上面的流光效果,我们也可以制作扫光效果
ae源文件
vue tab自动切换居中显示源文件下载
源文件包括 ae动画源文件
vue3 vite js框架源文件