应jy要求分享一下,第一次发文。具体原理看参考链接,讲得非常好!!!
效果
说明
白色块是独立的,点击是左右移动。每个tab固定宽度是20%,所以只兼容5个tab,可以自己按需求调整。(本来想给个动图的,但是公司电脑只能上传10k的文件)
代码实现
<template>
<div class="tab-list-cnt">
<div class="tab-list">
<div
v-for="tab in tabList"
:key="tab.name"
:class="'tab-item'"
@click="onTabClick(tab.name)"
>
<svg-icon color="#844ca8" :icon-class="tab.icon" class="tab-icon"/>
<div>{{ tab.label }}</div>
</div>
<div :style="{'transform': `translateX(${activeTabIndex * 100}%)`}" class="tab-selected">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
</div>
</template>
<script setup>
const props = defineProps({
tabList: {
type: Array,
default: () => [],
},
activeTab: {
type: String,
default: '',
},
})
const emit = defineEmits(['update:activeTab'])
const activeTabIndex = computed(() => {
return props.tabList.findIndex((tab) => tab.name === props.activeTab)
})
const onTabClick = (name) => {
emit('update:activeTab', name)
}
</script>
<style lang="scss" scoped>
$tab-height: 52px;
$active-color: #ffffff;
$default-color: #ede6f2;
$primary-color: #844ca8;
@mixin tabSelected($bgColor, $skewX) {
position: absolute;
width: 12px;
height: $tab-height;
background: $bgColor;
transform: skewX($skewX); // 重点
}
.tab-list-cnt {
position: sticky;
top: 0;
border-radius: 12px 12px 0 0;
background-color: $default-color;
overflow: hidden;
z-index: 2;
}
.tab-list {
position: relative;
display: flex;
border-radius: 12px 12px 0 0;
.tab-item {
position: relative;
display: flex;
justify-content: center;
align-items: center;
flex-basis: 20%;
height: $tab-height;
color: $primary-color;
font-size: 15px;
font-weight: 600;
cursor: pointer;
}
.tab-icon {
width: 18px;
height: 18px;
margin-right: 8px;
margin-top: 1px;
}
.tab-selected {
position: absolute;
width: 20%;
height: $tab-height;
background: #ffffff;
border-radius: 12px 12px 0 0;
box-shadow: 24px 40px 0 $active-color, -24px 40px 0 0 $active-color; // 重点
opacity: 1;
z-index: -1;
transition: .3s ease-in-out;
.left {
@include tabSelected($default-color, -15deg);
left: -18px;
border-bottom-right-radius: 12px;
}
.right {
@include tabSelected($default-color, 15deg);
right: -18px;
border-bottom-left-radius: 12px;
}
}
.tab-selected::before {
content: '';
@include tabSelected($active-color, -15deg);
left: -6px;
border-top-left-radius: 12px;
}
.tab-selected::after {
content: '';
@include tabSelected($active-color, 15deg);
right: -6px;
border-top-right-radius: 12px;
}
}
</style>