web-base-h5/components/raised-tabbar.vue

322 lines
7.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="raised-tabbar">
<!-- 背景遮罩层创建凸起效果 -->
<view class="tabbar-bg">
<view class="raised-circle"></view>
</view>
<!-- TabBar内容 -->
<view class="tabbar-content">
<!-- 左侧两个选项 -->
<view
v-for="(item, index) in leftItems"
:key="index"
class="tabbar-item"
:class="{ active: current === index }"
@click="tabbarChange(index)"
>
<view class="item-icon">
<image
:src="current === index ? item.activeIcon : item.inactiveIcon"
class="icon-normal"
/>
<view v-if="item.badge && item.badge > 0" class="badge">{{
item.badge
}}</view>
</view>
<text class="item-text" :class="{ active: current === index }">{{
item.text
}}</text>
</view>
<!-- 中间凸起的选项 -->
<view
class="tabbar-item center-item"
:class="{ active: current === 2 }"
@click="tabbarChange(2)"
>
<view class="center-icon-wrapper">
<view class="center-icon">
<image
:src="
current === 2 ? centerItem.activeIcon : centerItem.inactiveIcon
"
class="center-image"
/>
</view>
</view>
<text
class="item-text center-text"
:class="{ active: current === 2 }"
>{{ centerItem.text }}</text
>
</view>
<!-- 右侧两个选项 -->
<view
v-for="(item, index) in rightItems"
:key="index + 3"
class="tabbar-item"
:class="{ active: current === index + 3 }"
@click="tabbarChange(index + 3)"
>
<view class="item-icon">
<image
:src="current === index + 3 ? item.activeIcon : item.inactiveIcon"
class="icon-normal"
/>
<view v-if="item.badge && item.badge > 0" class="badge">{{
item.badge
}}</view>
</view>
<text class="item-text" :class="{ active: current === index + 3 }">{{
item.text
}}</text>
</view>
</view>
</view>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
name: 'RaisedTabbar',
props: {
current: {
type: Number,
default: 0,
},
},
data() {
return {
// 完整的路由列表
list: [
{
text: '首页',
path: 'pages/index/index',
},
{
text: '会员专区',
path: 'pages/specialArea/index',
},
{
text: '个人推广',
path: 'pages/mine/share/index',
},
{
text: '购物车',
path: 'pages/shoppingCar/index',
},
{
text: '我的',
path: 'pages/mine/index',
},
],
}
},
computed: {
...mapGetters(['shopCarLength']),
// 左侧两个选项
leftItems() {
return [
{
text: '首页',
activeIcon: require('@/static/images/one1.png'),
inactiveIcon: require('@/static/images/one2.png'),
},
{
text: '会员专区',
activeIcon: require('@/static/images/five1.jpg'),
inactiveIcon: require('@/static/images/five2.jpg'),
},
]
},
// 中间凸起选项
centerItem() {
return {
text: '个人推广',
activeIcon: require('@/static/images/code.svg'),
inactiveIcon: require('@/static/images/code.svg'),
}
},
// 右侧两个选项
rightItems() {
return [
{
text: '购物车',
activeIcon: require('@/static/images/three1.png'),
inactiveIcon: require('@/static/images/three2.png'),
badge: this.shopCarLength,
},
{
text: '我的',
activeIcon: require('@/static/images/fore1.png'),
inactiveIcon: require('@/static/images/fore2.png'),
},
]
},
},
methods: {
tabbarChange(index) {
this.$emit('change', index)
uni.switchTab({
url: '/' + this.list[index].path,
})
},
},
}
</script>
<style lang="scss" scoped>
.raised-tabbar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 1000;
.tabbar-bg {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 60px;
background: #ffffff;
// 添加底部安全区域
&::after {
content: '';
position: absolute;
bottom: -40px;
left: 0;
right: 0;
height: env(safe-area-inset-bottom);
background: #ffffff;
}
}
.tabbar-content {
position: relative;
display: flex;
align-items: flex-end;
height: 60px;
padding-bottom: 5px;
background: transparent;
.tabbar-item {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding-bottom: 5px;
position: relative;
.item-icon {
position: relative;
margin-bottom: 2px;
.icon-normal {
width: 20px;
height: 20px;
}
.badge {
position: absolute;
top: -5px;
right: -8px;
background: #ff4757;
color: white;
border-radius: 50%;
width: 16px;
height: 16px;
font-size: 10px;
text-align: center;
line-height: 16px;
display: flex;
align-items: center;
justify-content: center;
}
}
.item-text {
font-size: 10px;
color: #666666;
line-height: 1.2;
&.active {
color: #333333;
}
}
// 中间凸起的特殊样式
&.center-item {
position: relative;
.center-icon-wrapper {
position: absolute;
top: -58rpx;
background: #fff;
border-radius: 50%;
font-size: 0;
padding: 4rpx;
z-index: 10;
.center-icon {
width: 92rpx;
height: 92rpx;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
// box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
position: relative;
// 添加呼吸动画
// animation: breathe 3s ease-in-out infinite;
.center-image {
width: 92rpx;
height: 92rpx;
// position: absolute;
// top: -10rpx;
}
// 活跃状态
// &.active {
// background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
// }
}
}
.center-text {
margin-top: 25px;
font-size: 9px;
}
&.active {
.center-icon-wrapper .center-icon {
// background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
transform: scale(1.1);
transition: all 0.3s ease;
}
}
}
}
}
}
// 呼吸动画关键帧
@keyframes breathe {
0%,
100% {
transform: scale(1);
// box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
}
50% {
transform: scale(1.05);
// box-shadow: 0 6px 20px rgba(0, 0, 0, 0.25);
}
}
</style>