19 changed files with 574 additions and 140 deletions
@ -0,0 +1,257 @@ |
|||
<template> |
|||
<view> |
|||
<!-- 遮罩层 --> |
|||
<view class="overlay" v-if="showMenu" @click="closeMenu"></view> |
|||
|
|||
<!-- 固定导航按钮 --> |
|||
<view class="fixed-nav" :class="{ hidden: showMenu }" @click="showNavMenu"> |
|||
<image |
|||
class="nav-icon" |
|||
:class="{ rotated: iconRotated, 'bounce-back': iconBounceBack }" |
|||
src="https://static.ticket.sz-trip.com/epicSoul/taozi/nav-icon.png" |
|||
mode="aspectFill" |
|||
></image> |
|||
</view> |
|||
|
|||
<!-- 侧边导航菜单 --> |
|||
<view class="nav-menu" :class="{ show: showMenu }"> |
|||
<view |
|||
class="nav-item" |
|||
:class="{ 'item-active': isItemActive(item) }" |
|||
v-for="item in menuItems" |
|||
:key="item.targetIndex" |
|||
@click="() => jumpToPage(item.targetIndex)" |
|||
> |
|||
<view v-if="item.text.includes('#Chapter')" class="chapter-text"> |
|||
<text class="chapter-title">#Chapter</text> |
|||
<text :class="{ active: isItemActive(item) }" class="chapter-number"> |
|||
{{ item.text.replace("#Chapter", "") }} |
|||
</text> |
|||
</view> |
|||
<text v-else :class="{ active: isItemActive(item) }">{{ |
|||
item.text |
|||
}}</text> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: "SideNav", |
|||
props: { |
|||
currentIndex: { |
|||
type: Number, |
|||
default: 0, |
|||
}, |
|||
}, |
|||
data() { |
|||
return { |
|||
showMenu: false, |
|||
iconRotated: false, |
|||
iconBounceBack: false, |
|||
menuItems: [ |
|||
{ |
|||
text: "序章", |
|||
targetIndex: 0, |
|||
path: "/pig/home/home", |
|||
}, |
|||
{ |
|||
text: "第一章猪的起源", |
|||
targetIndex: 4, |
|||
path: "/pig/chapter1/chapter1", |
|||
}, |
|||
{ |
|||
text: "第二章驯为良伴", |
|||
targetIndex: 5, |
|||
path: "/pig/chapter2/chapter2", |
|||
}, |
|||
{ |
|||
text: "第三章身份之谜", |
|||
targetIndex: 6, |
|||
path: "/pig/chapter3/chapter3", |
|||
}, |
|||
{ |
|||
text: "第四章 东方之猪", |
|||
targetIndex: 7, |
|||
path: "/pig/chapter4/chapter4", |
|||
}, |
|||
{ |
|||
text: "点击购买", |
|||
targetIndex: 8, |
|||
path: "/subPackages/techan/detail?id=38", |
|||
}, |
|||
], |
|||
}; |
|||
}, |
|||
methods: { |
|||
showNavMenu() { |
|||
this.iconRotated = true; |
|||
setTimeout(() => { |
|||
this.showMenu = true; |
|||
}, 300); |
|||
}, |
|||
|
|||
closeMenu() { |
|||
this.showMenu = false; |
|||
setTimeout(() => { |
|||
this.iconBounceBack = true; |
|||
this.iconRotated = false; |
|||
setTimeout(() => { |
|||
this.iconBounceBack = false; |
|||
}, 500); |
|||
}, 300); |
|||
}, |
|||
jumpToPage(targetIndex) { |
|||
const menuItem = this.menuItems.find( |
|||
(item) => item.targetIndex === targetIndex |
|||
); |
|||
if (menuItem) { |
|||
// 如果有path属性,进行页面跳转 |
|||
if (menuItem.path) { |
|||
uni.navigateTo({ |
|||
url: |
|||
menuItem.path + |
|||
(targetIndex > 0 ? `?targetIndex=${targetIndex}` : ""), |
|||
}); |
|||
} else { |
|||
// 否则触发事件让父组件处理 |
|||
this.$emit("navigate", targetIndex); |
|||
} |
|||
} |
|||
this.closeMenu(); |
|||
}, |
|||
isItemActive(item) { |
|||
return this.currentIndex === item.targetIndex; |
|||
}, |
|||
}, |
|||
}; |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.overlay { |
|||
position: fixed; |
|||
top: 0; |
|||
left: 0; |
|||
right: 0; |
|||
bottom: 0; |
|||
background-color: rgba(0, 0, 0, 0.3); |
|||
z-index: 10; |
|||
} |
|||
|
|||
.fixed-nav { |
|||
width: 80rpx; |
|||
height: 80rpx; |
|||
background-color: rgb(0 0 0 / 0.7); |
|||
border-radius: 10rpx 0 0 10rpx; |
|||
position: fixed; |
|||
right: 0; |
|||
top: 0; |
|||
bottom: 0; |
|||
margin: auto 0; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
z-index: 9; |
|||
transition: transform 0.3s ease, opacity 0.3s ease; |
|||
} |
|||
|
|||
.fixed-nav.hidden { |
|||
transform: translateX(100%); |
|||
opacity: 0; |
|||
pointer-events: none; |
|||
} |
|||
|
|||
.nav-icon { |
|||
width: 35rpx; |
|||
height: 35rpx; |
|||
transition: transform 0.3s ease; |
|||
} |
|||
|
|||
.nav-icon.rotated { |
|||
transform: rotate(180deg); |
|||
} |
|||
|
|||
.nav-icon.bounce-back { |
|||
animation: bounceRotation 0.5s ease; |
|||
} |
|||
|
|||
@keyframes bounceRotation { |
|||
0% { |
|||
transform: rotate(180deg); |
|||
} |
|||
|
|||
50% { |
|||
transform: rotate(-20deg); |
|||
} |
|||
|
|||
75% { |
|||
transform: rotate(10deg); |
|||
} |
|||
|
|||
100% { |
|||
transform: rotate(0deg); |
|||
} |
|||
} |
|||
|
|||
.nav-menu { |
|||
position: fixed; |
|||
top: 50%; |
|||
right: 0; |
|||
transform: translate(100%, -50%); |
|||
z-index: 11; |
|||
background-color: rgba(255, 255, 255, 0.95); |
|||
border-radius: 16rpx 0 0 16rpx; |
|||
box-shadow: -4px 0 15px rgba(0, 0, 0, 0.1); |
|||
transition: transform 0.3s ease; |
|||
} |
|||
|
|||
.nav-menu.show { |
|||
transform: translate(0, -50%); |
|||
} |
|||
|
|||
.nav-item { |
|||
padding: 20rpx; |
|||
text-align: center; |
|||
|
|||
text { |
|||
color: #333; |
|||
opacity: 0.7; |
|||
font-size: 28rpx; |
|||
} |
|||
} |
|||
|
|||
.item-active { |
|||
background-color: rgba(0, 0, 0, 0.1); |
|||
} |
|||
|
|||
.nav-item .active { |
|||
color: #333; |
|||
opacity: 1; |
|||
} |
|||
|
|||
.chapter-text { |
|||
display: flex; |
|||
flex-direction: column; |
|||
align-items: center; |
|||
line-height: 1.3; |
|||
} |
|||
|
|||
.chapter-title { |
|||
color: #333; |
|||
opacity: 0.7; |
|||
font-size: 24rpx; |
|||
} |
|||
|
|||
.chapter-number { |
|||
color: #333; |
|||
opacity: 0.7; |
|||
font-size: 28rpx; |
|||
margin-top: 8rpx; |
|||
} |
|||
|
|||
.item-active .chapter-title, |
|||
.item-active .chapter-number.active { |
|||
opacity: 1; |
|||
} |
|||
</style> |
Loading…
Reference in new issue