You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

339 lines
8.4 KiB

<template>
<view>
<TitleHeader />
<swiper class="main-swiper" :vertical="true" :current="currentIndex" @change="handleSwiperChange"
:duration="300" :style="{ height: `calc(100vh - ${titleHeight}px)` }">
<swiper-item>
<view class="page-container">
<template v-if="loadedPages[0]">
<image v-show="shouldShowContent(0)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter2/bg1.png"
:lazy-load="true" mode="aspectFill"></image>
<image v-show="shouldShowContent(0)" class="layer-img1"
:class="{'slide-in-from-left': animationStates[0], 'hidden': !animationStates[0]}"
src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter2/bg1-info.png" :lazy-load="true" mode="aspectFill" />
</template>
</view>
</swiper-item>
<swiper-item>
<view class="page-container">
<view class="loadedPages-three-title">
<view class="txt">
#Chapter 贰
</view>
<view class="txt">
IP Art Exhibition
</view>
</view>
<template v-if="loadedPages[1]">
<image v-show="shouldShowContent(1)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter2/bg2.png"
:lazy-load="true" mode="aspectFill"></image>
<image v-show="shouldShowContent(1)" class="layer-img2"
:class="{'slide-in-from-left': animationStates[1], 'hidden': !animationStates[1]}"
src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter2/bg2-info.png" :lazy-load="true" mode="aspectFill" />
</template>
</view>
</swiper-item>
<swiper-item>
<view class="page-container">
<template v-if="loadedPages[2]">
<image v-show="shouldShowContent(2)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter2/bg3.png"
:lazy-load="true" mode="aspectFill"></image>
<image v-show="shouldShowContent(2)" class="layer-img3"
:class="{'slide-in-from-left': animationStates[2], 'hidden': !animationStates[2]}"
src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter2/bg3-info.png" :lazy-load="true" mode="aspectFill" />
</template>
</view>
</swiper-item>
<swiper-item>
<view class="page-container">
<template v-if="loadedPages[3]">
<image v-show="shouldShowContent(3)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter2/bg4.png"
:lazy-load="true" mode="aspectFill"></image>
<image v-show="shouldShowContent(3)" class="layer-img4"
:class="{'slide-in-from-left': animationStates[3], 'hidden': !animationStates[3]}"
src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter2/bg4-info.png" :lazy-load="true" mode="aspectFill" />
</template>
</view>
</swiper-item>
<swiper-item>
<view class="page-container">
<template v-if="loadedPages[4]">
<image v-show="shouldShowContent(4)" class="bg-image" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter2/bg5.png"
:lazy-load="true" mode="aspectFill"></image>
<video v-show="shouldShowContent(4)" ref="videoPlayer" id="videoPlayer"
class="loadedPages-video" src="https://static.ticket.sz-trip.com/epicSoul/taozi/chapter2/bg5-video.mp4"
:autoplay="currentIndex === 4" :loop="true" :controls="true" :show-play-btn="true"
:enable-progress-gesture="true" @error="handleVideoError"></video>
<view @click="goBack" class="back-btn" type="default">
<image class="back-icon" src="https://static.ticket.sz-trip.com/epicSoul/taozi/back.png" mode="aspectFill"></image>
</view>
</template>
</view>
</swiper-item>
</swiper>
<AudioControl :top="'230rpx'" audioSrc="https://des.js-dyyj.com/data/2025/09/05/286e6a8d-4433-4d69-b705-74b3f4237667.MP3" />
<MusicControl />
</view>
</template>
<script>
import AudioControl from '@/components/AudioControl.vue';
import MusicControl from '@/components/MusicControl.vue';
import TitleHeader from '@/components/TitleHeader.vue';
export default {
components: {
MusicControl,
TitleHeader,
AudioControl
},
data() {
return {
currentIndex: 0,
videoPlayer: null,
videoContext: null,
loadedPages: {
0: false,
1: false,
2: false,
3: false,
4: false
},
animationStates: {
0: false,
1: false,
2: false,
3: false,
4: false
},
preloadBuffer: 1,
titleHeight: 0
};
},
watch: {
currentIndex(newIndex) {
for (let i = Math.max(0, newIndex - this.preloadBuffer); i <= Math.min(9, newIndex + this
.preloadBuffer); i++) {
this.loadedPages[i] = true;
}
}
},
mounted() {
this.titleHeight = uni.getStorageSync('titleHeight')
for (let i = 0; i <= Math.min(1 + this.preloadBuffer, 9); i++) {
this.loadedPages[i] = true;
}
setTimeout(() => {
this.animationStates[this.currentIndex] = true;
}, 50);
this.$nextTick(() => {
try {
this.videoContext = uni.createVideoContext('videoPlayer');
} catch (error) {
console.error('初始化视频上下文失败:', error);
}
});
},
methods: {
handleSwiperChange(e) {
const newIndex = e.detail.current;
const oldIndex = this.currentIndex;
this.currentIndex = newIndex;
this.animationStates[newIndex] = false;
setTimeout(() => {
this.animationStates[newIndex] = true;
}, 50);
this.$nextTick(() => {
this.handleVideoPlayback(oldIndex, newIndex);
});
},
handleVideoPlayback(oldIndex, newIndex) {
if (!this.videoContext) {
try {
this.videoContext = uni.createVideoContext('videoPlayer');
} catch (error) {}
}
if (!this.videoContext) return;
if (newIndex === 4) {
try {
this.videoContext.play();
} catch (error) {}
} else if (oldIndex === 4) {
try {
this.videoContext.pause();
this.videoContext.seek(0);
} catch (error) {
console.error('视频暂停失败:', error);
}
}
},
handleVideoError(e) {
uni.showToast({
title: '视频加载失败',
icon: 'none'
});
},
shouldShowContent(index) {
return Math.abs(index - this.currentIndex) <= this.preloadBuffer;
},
goBack() {
uni.navigateTo({
url: '/taozi/home/home?targetIndex=6'
});
}
},
onShow() {
if (this.currentIndex === 4 && this.videoContext) {
this.$nextTick(() => {
this.videoContext.play();
});
}
},
onHide() {
if (this.videoContext) {
this.videoContext.pause();
}
}
};
</script>
<style lang="scss" scoped>
.main-swiper {
width: 100%;
height: 100vh;
}
.page-container {
height: 100%;
position: relative;
overflow: hidden;
}
.bg-image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
}
.layer-img1 {
position: absolute;
width: 500rpx;
height: 800rpx;
z-index: 2;
top: 120rpx;
left: 60rpx;
}
.layer-img2 {
position: absolute;
top: 0;
left: 0;
width: 640rpx;
height: 750rpx;
z-index: 2;
}
.layer-img3 {
position: absolute;
bottom: 0;
left: 30rpx;
width: 550rpx;
height: 1200rpx;
z-index: 2;
}
.layer-img4 {
position: absolute;
bottom: 50rpx;
left: 30rpx;
width: 400rpx;
height: 900rpx;
z-index: 2;
}
.hidden {
opacity: 0;
}
.slide-in-from-left {
animation: slideInLeft 1.2s ease-out forwards;
}
@keyframes slideInLeft {
0% {
opacity: 0;
transform: translateX(-100px);
}
100% {
opacity: 1;
transform: translateX(0);
}
}
@font-face {
font-family: 'SourceHanSerif-Regular';
src: url(https://static.ticket.sz-trip.com/epicSoul/taozi/fonts/SourceHanSerifSC-Regular.otf);
}
.loadedPages-three-title {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
margin-top: 30rpx;
z-index: 9;
position: absolute;
.txt {
font-size: 24rpx;
color: #333;
font-family: SourceHanSerif-Regular;
display: flex;
flex-direction: column;
align-items: center;
text {
display: block;
}
}
.txt:first-child {
margin-left: 30rpx;
}
.txt:last-child {
margin-right: 30rpx;
}
}
.loadedPages-video {
width: 100%;
height: 350rpx;
z-index: 9;
margin-top: 150rpx;
}
.back-btn {
position: absolute;
top: 50rpx;
left: 50rpx;
z-index: 2;
background-color: rgb(0 0 0 / 0.3);
border-radius: 50%;
width: 80rpx;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
}
.back-icon {
width: 50rpx;
height: 50rpx;
}
</style>