手动实现tabs-圆角及反圆角效果

955 阅读1分钟

参考链接-实现tabs圆角及反圆角效果(PLUS)

应jy要求分享一下,第一次发文。具体原理看参考链接,讲得非常好!!!

效果

image.png

说明

白色块是独立的,点击是左右移动。每个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>