v1.2.6
1、更换loading页面开始按钮 2、长图页五个商圈分别增加对应的视频地址 3、视频播放按钮吉视频播放器,分别封装为组件,5个商圈组件进行引用
This commit is contained in:
parent
d89ce10c34
commit
cea4f8b67d
|
|
@ -1,5 +1,7 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, computed } from 'vue'
|
import { ref, onMounted, computed } from 'vue'
|
||||||
|
import VideoPlayButton from './VideoPlayButton.vue'
|
||||||
|
import VideoPlayerModal from './VideoPlayerModal.vue'
|
||||||
|
|
||||||
// 组件属性
|
// 组件属性
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
|
@ -12,6 +14,11 @@ const props = defineProps({
|
||||||
scrollPosition: {
|
scrollPosition: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 0
|
default: 0
|
||||||
|
},
|
||||||
|
// 视频地址
|
||||||
|
videoUrl: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -23,6 +30,8 @@ const sealCollected = ref(false)
|
||||||
|
|
||||||
// 福字点击区域状态
|
// 福字点击区域状态
|
||||||
const sq2ImageVisible = ref(false)
|
const sq2ImageVisible = ref(false)
|
||||||
|
// 视频播放状态
|
||||||
|
const showVideoPlayer = ref(false)
|
||||||
|
|
||||||
// 计算视差效果的偏移量
|
// 计算视差效果的偏移量
|
||||||
const parallaxOffset = computed(() => {
|
const parallaxOffset = computed(() => {
|
||||||
|
|
@ -46,15 +55,25 @@ const openWebview = () => {
|
||||||
},
|
},
|
||||||
fail: (err) => {
|
fail: (err) => {
|
||||||
console.error('Failed to open webview:', err)
|
console.error('Failed to open webview:', err)
|
||||||
showToast({
|
uni.showToast({
|
||||||
message: '页面打开失败',
|
title: '页面打开失败',
|
||||||
icon: 'error',
|
icon: 'none',
|
||||||
duration: 1500
|
duration: 1500
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 打开视频播放器
|
||||||
|
const openVideoPlayer = () => {
|
||||||
|
showVideoPlayer.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭视频播放器
|
||||||
|
const closeVideoPlayer = () => {
|
||||||
|
showVideoPlayer.value = false
|
||||||
|
}
|
||||||
|
|
||||||
// 页面挂载时的初始化
|
// 页面挂载时的初始化
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 添加动画类,触发入场动画
|
// 添加动画类,触发入场动画
|
||||||
|
|
@ -91,6 +110,17 @@ onMounted(() => {
|
||||||
@click="openWebview"
|
@click="openWebview"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<!-- 视频播放按钮 -->
|
||||||
|
<VideoPlayButton @play="openVideoPlayer" />
|
||||||
|
|
||||||
|
<!-- 视频播放器弹窗 -->
|
||||||
|
<VideoPlayerModal
|
||||||
|
:video-url="props.videoUrl"
|
||||||
|
:visible="showVideoPlayer"
|
||||||
|
@close="closeVideoPlayer"
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, onUnmounted, computed, getCurrentInstance as vueGetCurrentInstance, watch } from 'vue'
|
import { ref, onMounted, onUnmounted, computed, getCurrentInstance as vueGetCurrentInstance, watch } from 'vue'
|
||||||
import ImagePreloader from '@/utils/preload'
|
import ImagePreloader from '@/utils/preload'
|
||||||
|
import VideoPlayButton from './VideoPlayButton.vue'
|
||||||
|
import VideoPlayerModal from './VideoPlayerModal.vue'
|
||||||
|
|
||||||
// 获取 Vue 实例
|
// 获取 Vue 实例
|
||||||
const instance = vueGetCurrentInstance()
|
const instance = vueGetCurrentInstance()
|
||||||
|
|
@ -14,6 +16,10 @@ const props = defineProps({
|
||||||
scrollPosition: {
|
scrollPosition: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 0
|
default: 0
|
||||||
|
},
|
||||||
|
videoUrl: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -23,6 +29,8 @@ const emit = defineEmits(['collect-seal'])
|
||||||
const sq3ImageVisible = ref(false)
|
const sq3ImageVisible = ref(false)
|
||||||
// 是否已经收集福印
|
// 是否已经收集福印
|
||||||
const sealCollected = ref(false)
|
const sealCollected = ref(false)
|
||||||
|
// 视频播放状态
|
||||||
|
const showVideoPlayer = ref(false)
|
||||||
|
|
||||||
// 计算视差效果的偏移量
|
// 计算视差效果的偏移量
|
||||||
const parallaxOffset = computed(() => {
|
const parallaxOffset = computed(() => {
|
||||||
|
|
@ -467,6 +475,16 @@ const resetDuckPosition = () => {
|
||||||
console.log('鸭子已回归原始位置:', duckX.value, duckY.value)
|
console.log('鸭子已回归原始位置:', duckX.value, duckY.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 打开视频播放器
|
||||||
|
const openVideoPlayer = () => {
|
||||||
|
showVideoPlayer.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭视频播放器
|
||||||
|
const closeVideoPlayer = () => {
|
||||||
|
showVideoPlayer.value = false
|
||||||
|
}
|
||||||
|
|
||||||
// 预加载图片
|
// 预加载图片
|
||||||
const preloadImages = async () => {
|
const preloadImages = async () => {
|
||||||
if (imagesLoaded.value || isPreloading.value) return
|
if (imagesLoaded.value || isPreloading.value) return
|
||||||
|
|
@ -590,6 +608,17 @@ onUnmounted(() => {
|
||||||
class="drag-trigger-area"
|
class="drag-trigger-area"
|
||||||
@touchstart="startDrag"
|
@touchstart="startDrag"
|
||||||
></view>
|
></view>
|
||||||
|
|
||||||
|
<!-- 视频播放按钮 -->
|
||||||
|
<VideoPlayButton @play="openVideoPlayer" />
|
||||||
|
|
||||||
|
<!-- 视频播放器弹窗 -->
|
||||||
|
<VideoPlayerModal
|
||||||
|
:video-url="props.videoUrl"
|
||||||
|
:visible="showVideoPlayer"
|
||||||
|
@close="closeVideoPlayer"
|
||||||
|
/>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -692,4 +721,6 @@ onUnmounted(() => {
|
||||||
height: 100rpx;
|
height: 100rpx;
|
||||||
z-index: 30;
|
z-index: 30;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
@ -111,7 +111,7 @@ onMounted(() => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 进度条区域 -->
|
<!-- 进度条区域 -->
|
||||||
<div class="progress-container">
|
<div v-if="!startButtonVisible" class="progress-container">
|
||||||
<div class="progress-bar">
|
<div class="progress-bar">
|
||||||
<div class="progress-fill" :style="{ width: `${loadingProgress}%` }"></div>
|
<div class="progress-fill" :style="{ width: `${loadingProgress}%` }"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -190,8 +190,8 @@ onMounted(() => {
|
||||||
.start-button {
|
.start-button {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 20vh;
|
bottom: 20vh;
|
||||||
width: 300rpx;
|
width: 496rpx;
|
||||||
height: 100rpx;
|
height: 97rpx;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
animation: pulse 1.5s infinite;
|
animation: pulse 1.5s infinite;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, computed, watch } from 'vue'
|
import { ref, onMounted, computed, watch } from 'vue'
|
||||||
import ImageGalleryModal from './ImageGalleryModal.vue'
|
import ImageGalleryModal from './ImageGalleryModal.vue'
|
||||||
|
import VideoPlayButton from './VideoPlayButton.vue'
|
||||||
|
import VideoPlayerModal from './VideoPlayerModal.vue'
|
||||||
import ImagePreloader from '@/utils/preload';
|
import ImagePreloader from '@/utils/preload';
|
||||||
|
|
||||||
// 组件属性
|
// 组件属性
|
||||||
|
|
@ -14,6 +16,11 @@ const props = defineProps({
|
||||||
scrollPosition: {
|
scrollPosition: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 0
|
default: 0
|
||||||
|
},
|
||||||
|
// 视频地址
|
||||||
|
videoUrl: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -24,6 +31,8 @@ const emit = defineEmits(['collect-seal'])
|
||||||
const sq3ImageVisible = ref(false)
|
const sq3ImageVisible = ref(false)
|
||||||
// 是否已经收集福印
|
// 是否已经收集福印
|
||||||
const sealCollected = ref(false)
|
const sealCollected = ref(false)
|
||||||
|
// 视频播放状态
|
||||||
|
const showVideoPlayer = ref(false)
|
||||||
|
|
||||||
// 图片加载状态
|
// 图片加载状态
|
||||||
const imagesLoaded = ref(false)
|
const imagesLoaded = ref(false)
|
||||||
|
|
@ -96,6 +105,16 @@ const closeGallery = () => {
|
||||||
galleryVisible.value = false
|
galleryVisible.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 打开视频播放器
|
||||||
|
const openVideoPlayer = () => {
|
||||||
|
showVideoPlayer.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭视频播放器
|
||||||
|
const closeVideoPlayer = () => {
|
||||||
|
showVideoPlayer.value = false
|
||||||
|
}
|
||||||
|
|
||||||
// 页面挂载时的初始化
|
// 页面挂载时的初始化
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 添加动画类,触发入场动画
|
// 添加动画类,触发入场动画
|
||||||
|
|
@ -157,6 +176,18 @@ onMounted(() => {
|
||||||
@close="closeGallery"
|
@close="closeGallery"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<!-- 视频播放按钮 -->
|
||||||
|
<VideoPlayButton @play="openVideoPlayer" />
|
||||||
|
|
||||||
|
|
||||||
|
<!-- 视频播放器弹窗 -->
|
||||||
|
<VideoPlayerModal
|
||||||
|
:video-url="props.videoUrl"
|
||||||
|
:visible="showVideoPlayer"
|
||||||
|
@close="closeVideoPlayer"
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -305,53 +336,6 @@ onMounted(() => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 烟花效果 */
|
|
||||||
.fireworks {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
pointer-events: none;
|
|
||||||
z-index: 20;
|
|
||||||
}
|
|
||||||
|
|
||||||
.firework {
|
|
||||||
position: absolute;
|
|
||||||
font-size: 2rem;
|
|
||||||
opacity: 0;
|
|
||||||
animation: firework 3s infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.firework-1 {
|
|
||||||
top: 10%;
|
|
||||||
left: 20%;
|
|
||||||
animation-delay: 0s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.firework-2 {
|
|
||||||
top: 15%;
|
|
||||||
right: 25%;
|
|
||||||
animation-delay: 1s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.firework-3 {
|
|
||||||
top: 8%;
|
|
||||||
right: 15%;
|
|
||||||
animation-delay: 2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.firework-4 {
|
|
||||||
top: 12%;
|
|
||||||
left: 25%;
|
|
||||||
animation-delay: 3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes firework {
|
|
||||||
0%, 100% { opacity: 0; transform: scale(0); }
|
|
||||||
50% { opacity: 1; transform: scale(1.5); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 福印收集标记 */
|
/* 福印收集标记 */
|
||||||
.seal-collected-mark {
|
.seal-collected-mark {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
@ -443,19 +427,4 @@ onMounted(() => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 响应式设计 */
|
|
||||||
@media (max-width: 640px) {
|
|
||||||
.fu-word {
|
|
||||||
font-size: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lantern {
|
|
||||||
font-size: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.interaction-area {
|
|
||||||
width: 100px;
|
|
||||||
height: 80px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, onUnmounted, computed, watch } from 'vue'
|
import { ref, onMounted, onUnmounted, computed, watch } from 'vue'
|
||||||
|
import VideoPlayButton from './VideoPlayButton.vue'
|
||||||
|
import VideoPlayerModal from './VideoPlayerModal.vue'
|
||||||
|
|
||||||
// 组件属性
|
// 组件属性
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
|
@ -12,6 +14,11 @@ const props = defineProps({
|
||||||
scrollPosition: {
|
scrollPosition: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 0
|
default: 0
|
||||||
|
},
|
||||||
|
// 视频地址
|
||||||
|
videoUrl: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -27,6 +34,8 @@ const musicPlayer = ref(null)
|
||||||
|
|
||||||
// 福字点击区域状态
|
// 福字点击区域状态
|
||||||
const sq1ImageVisible = ref(false)
|
const sq1ImageVisible = ref(false)
|
||||||
|
// 视频播放状态
|
||||||
|
const showVideoPlayer = ref(false)
|
||||||
|
|
||||||
// 场景高度
|
// 场景高度
|
||||||
const sceneHeight = ref(0)
|
const sceneHeight = ref(0)
|
||||||
|
|
@ -144,6 +153,16 @@ const calculateHeight = () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 打开视频播放器
|
||||||
|
const openVideoPlayer = () => {
|
||||||
|
showVideoPlayer.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭视频播放器
|
||||||
|
const closeVideoPlayer = () => {
|
||||||
|
showVideoPlayer.value = false
|
||||||
|
}
|
||||||
|
|
||||||
// 组件卸载时清理
|
// 组件卸载时清理
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
if (musicPlayer.value) {
|
if (musicPlayer.value) {
|
||||||
|
|
@ -194,6 +213,12 @@ onUnmounted(() => {
|
||||||
<!-- 舞狮动画 -->
|
<!-- 舞狮动画 -->
|
||||||
<div class="lion-dance"></div>
|
<div class="lion-dance"></div>
|
||||||
|
|
||||||
|
<!-- 视频播放按钮 -->
|
||||||
|
<VideoPlayButton @play="openVideoPlayer" />
|
||||||
|
|
||||||
|
<!-- 视频播放器弹窗 -->
|
||||||
|
<VideoPlayerModal :video-url="props.videoUrl" :visible="showVideoPlayer" @close="closeVideoPlayer" />
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -78,31 +78,36 @@ const scenes = ref([
|
||||||
id: 'dongzhimen',
|
id: 'dongzhimen',
|
||||||
name: '东直门商圈',
|
name: '东直门商圈',
|
||||||
description: '京城东部的交通枢纽和商业中心',
|
description: '京城东部的交通枢纽和商业中心',
|
||||||
collectedItem: '团圆福筷'
|
collectedItem: '团圆福筷',
|
||||||
|
videoUrl: 'http://192.168.2.149:8090/sample-3.mp4'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'longfusi',
|
id: 'longfusi',
|
||||||
name: '隆福寺商圈',
|
name: '隆福寺商圈',
|
||||||
description: '传统文化与现代艺术融合的潮流地标',
|
description: '传统文化与现代艺术融合的潮流地标',
|
||||||
collectedItem: '文化福灯'
|
collectedItem: '文化福灯',
|
||||||
|
videoUrl: 'http://192.168.2.149:8090/sample-3.mp4'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'wangfujing',
|
id: 'wangfujing',
|
||||||
name: '王府井商圈',
|
name: '王府井商圈',
|
||||||
description: '北京最繁华的商业中心之一',
|
description: '北京最繁华的商业中心之一',
|
||||||
collectedItem: '金袋福卡'
|
collectedItem: '金袋福卡',
|
||||||
|
videoUrl: 'http://192.168.2.149:8090/sample-3.mp4'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'chongwen',
|
id: 'chongwen',
|
||||||
name: '崇文门商圈',
|
name: '崇文门商圈',
|
||||||
description: '融合传统文化与现代商业的活力区域',
|
description: '融合传统文化与现代商业的活力区域',
|
||||||
collectedItem: '国潮福字'
|
collectedItem: '国潮福字',
|
||||||
|
videoUrl: 'http://192.168.2.149:8090/sample-3.mp4'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'qianmen',
|
id: 'qianmen',
|
||||||
name: '前门商圈',
|
name: '前门商圈',
|
||||||
description: '北京最具历史文化底蕴的商圈之一',
|
description: '北京最具历史文化底蕴的商圈之一',
|
||||||
collectedItem: '非遗福印'
|
collectedItem: '非遗福印',
|
||||||
|
videoUrl: 'http://192.168.2.149:8090/sample-3.mp4'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'home',
|
id: 'home',
|
||||||
|
|
@ -611,6 +616,7 @@ onUnmounted(() => {
|
||||||
<DongzhimenScene
|
<DongzhimenScene
|
||||||
:active="activeSceneIndex === 1"
|
:active="activeSceneIndex === 1"
|
||||||
:scroll-position="scrollContainer && scrollContainer.value ? scrollContainer.value.scrollTop : 0"
|
:scroll-position="scrollContainer && scrollContainer.value ? scrollContainer.value.scrollTop : 0"
|
||||||
|
:video-url="scenes[1].videoUrl"
|
||||||
@collect-seal="collectSeal(1)"
|
@collect-seal="collectSeal(1)"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
@ -618,6 +624,7 @@ onUnmounted(() => {
|
||||||
<LongfusiScene
|
<LongfusiScene
|
||||||
:active="activeSceneIndex === 2"
|
:active="activeSceneIndex === 2"
|
||||||
:scroll-position="scrollContainer && scrollContainer.value ? scrollContainer.value.scrollTop : 0"
|
:scroll-position="scrollContainer && scrollContainer.value ? scrollContainer.value.scrollTop : 0"
|
||||||
|
:video-url="scenes[2].videoUrl"
|
||||||
@collect-seal="collectSeal(2)"
|
@collect-seal="collectSeal(2)"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
@ -625,6 +632,7 @@ onUnmounted(() => {
|
||||||
<WangfujingScene
|
<WangfujingScene
|
||||||
:active="activeSceneIndex === 3"
|
:active="activeSceneIndex === 3"
|
||||||
:scroll-position="scrollContainer?.value?.scrollTop || 0"
|
:scroll-position="scrollContainer?.value?.scrollTop || 0"
|
||||||
|
:video-url="scenes[3].videoUrl"
|
||||||
@collect-seal="collectSeal(3)"
|
@collect-seal="collectSeal(3)"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
@ -632,6 +640,7 @@ onUnmounted(() => {
|
||||||
<ChongwenScene
|
<ChongwenScene
|
||||||
:active="activeSceneIndex === 4"
|
:active="activeSceneIndex === 4"
|
||||||
:scroll-position="scrollContainer?.value?.scrollTop || 0"
|
:scroll-position="scrollContainer?.value?.scrollTop || 0"
|
||||||
|
:video-url="scenes[4].videoUrl"
|
||||||
@collect-seal="collectSeal(4)"
|
@collect-seal="collectSeal(4)"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
@ -639,6 +648,7 @@ onUnmounted(() => {
|
||||||
<QianmenScene
|
<QianmenScene
|
||||||
:active="activeSceneIndex === 5"
|
:active="activeSceneIndex === 5"
|
||||||
:scroll-position="scrollContainer?.value?.scrollTop || 0"
|
:scroll-position="scrollContainer?.value?.scrollTop || 0"
|
||||||
|
:video-url="scenes[5].videoUrl"
|
||||||
@collect-seal="collectSeal(5)"
|
@collect-seal="collectSeal(5)"
|
||||||
@height-changed="handleQianmenHeightChanged"
|
@height-changed="handleQianmenHeightChanged"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,94 @@
|
||||||
|
<script setup>
|
||||||
|
import { defineEmits } from 'vue'
|
||||||
|
|
||||||
|
// 组件事件
|
||||||
|
const emit = defineEmits(['play'])
|
||||||
|
|
||||||
|
// 处理播放按钮点击
|
||||||
|
const handlePlayClick = () => {
|
||||||
|
emit('play')
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="video-play-button-container" @click="handlePlayClick">
|
||||||
|
<!-- 背景层,单独进行呼吸动画 -->
|
||||||
|
<div class="video-play-button-bg"></div>
|
||||||
|
<!-- 内容层,保持静态 -->
|
||||||
|
<div class="video-play-button-content">
|
||||||
|
<img src="/static/images/icon_music1.png" alt="播放视频" class="video-icon" />
|
||||||
|
<span class="video-text">观看视频</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* 视频播放按钮容器 */
|
||||||
|
.video-play-button-container {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 100rpx;
|
||||||
|
right: 5rpx;
|
||||||
|
width: 120rpx;
|
||||||
|
height: 120rpx;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 50;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 背景层,单独进行呼吸动画 */
|
||||||
|
.video-play-button-bg {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: rgba(0, 0, 0, 0.3);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
animation: breathe 2s infinite ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 内容层,保持静态 */
|
||||||
|
.video-play-button-content {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 鼠标悬停效果 */
|
||||||
|
.video-play-button-container:hover .video-play-button-bg {
|
||||||
|
background-color: rgba(0, 0, 0, 0.9);
|
||||||
|
transform: scale(1.05);
|
||||||
|
animation: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-icon {
|
||||||
|
width: 40rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
margin-bottom: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-text {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: white;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 呼吸动画 */
|
||||||
|
@keyframes breathe {
|
||||||
|
0%, 100% {
|
||||||
|
transform: scale(1);
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: scale(1.1);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,105 @@
|
||||||
|
<script setup>
|
||||||
|
import { defineProps, defineEmits } from 'vue'
|
||||||
|
|
||||||
|
// 组件属性
|
||||||
|
const props = defineProps({
|
||||||
|
// 视频地址
|
||||||
|
videoUrl: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
// 是否显示
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 组件事件
|
||||||
|
const emit = defineEmits(['close'])
|
||||||
|
|
||||||
|
// 处理关闭按钮点击
|
||||||
|
const handleClose = () => {
|
||||||
|
emit('close')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理弹窗背景点击
|
||||||
|
const handleModalClick = () => {
|
||||||
|
emit('close')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 阻止内容区域冒泡
|
||||||
|
const handleContentClick = (e) => {
|
||||||
|
e.stopPropagation()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div v-if="visible" class="video-modal">
|
||||||
|
<div class="video-modal-content" @click="handleContentClick">
|
||||||
|
<div class="video-close-button" @click="handleClose">
|
||||||
|
<span>×</span>
|
||||||
|
</div>
|
||||||
|
<video
|
||||||
|
:src="videoUrl"
|
||||||
|
class="video-player"
|
||||||
|
controls
|
||||||
|
autoplay
|
||||||
|
loop
|
||||||
|
></video>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* 视频播放器弹窗样式 */
|
||||||
|
.video-modal {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
background-color: rgba(0, 0, 0, 0.9);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-modal-content {
|
||||||
|
position: relative;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
width: 720rpx;
|
||||||
|
height: 405rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-close-button {
|
||||||
|
position: absolute;
|
||||||
|
top: 10rpx;
|
||||||
|
right: 10rpx;
|
||||||
|
width: 40rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
background-color: rgba(0, 0, 0, 0.7);
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-close-button span {
|
||||||
|
color: white;
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
line-height: 30rpx;
|
||||||
|
height: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-player {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: #000;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, computed, watch } from 'vue'
|
import { ref, onMounted, computed, watch } from 'vue'
|
||||||
import ImageGalleryModal from './ImageGalleryModal.vue'
|
import ImageGalleryModal from './ImageGalleryModal.vue'
|
||||||
|
import VideoPlayButton from './VideoPlayButton.vue'
|
||||||
|
import VideoPlayerModal from './VideoPlayerModal.vue'
|
||||||
import ImagePreloader from '@/utils/preload';
|
import ImagePreloader from '@/utils/preload';
|
||||||
|
|
||||||
// 组件属性
|
// 组件属性
|
||||||
|
|
@ -14,6 +16,11 @@ const props = defineProps({
|
||||||
scrollPosition: {
|
scrollPosition: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 0
|
default: 0
|
||||||
|
},
|
||||||
|
// 视频地址
|
||||||
|
videoUrl: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -22,6 +29,8 @@ const emit = defineEmits(['collect-seal'])
|
||||||
|
|
||||||
// 福字点击区域状态
|
// 福字点击区域状态
|
||||||
const sq3ImageVisible = ref(false)
|
const sq3ImageVisible = ref(false)
|
||||||
|
// 视频播放状态
|
||||||
|
const showVideoPlayer = ref(false)
|
||||||
|
|
||||||
// 图片加载状态
|
// 图片加载状态
|
||||||
const imagesLoaded = ref(false)
|
const imagesLoaded = ref(false)
|
||||||
|
|
@ -94,6 +103,16 @@ const closeGallery = () => {
|
||||||
galleryVisible.value = false
|
galleryVisible.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 打开视频播放器
|
||||||
|
const openVideoPlayer = () => {
|
||||||
|
showVideoPlayer.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭视频播放器
|
||||||
|
const closeVideoPlayer = () => {
|
||||||
|
showVideoPlayer.value = false
|
||||||
|
}
|
||||||
|
|
||||||
// 页面挂载时的初始化
|
// 页面挂载时的初始化
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 添加动画类,触发入场动画
|
// 添加动画类,触发入场动画
|
||||||
|
|
@ -141,6 +160,17 @@ onMounted(() => {
|
||||||
@close="closeGallery"
|
@close="closeGallery"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<!-- 视频播放按钮 -->
|
||||||
|
<VideoPlayButton @play="openVideoPlayer" />
|
||||||
|
|
||||||
|
<!-- 视频播放器弹窗 -->
|
||||||
|
<VideoPlayerModal
|
||||||
|
:video-url="props.videoUrl"
|
||||||
|
:visible="showVideoPlayer"
|
||||||
|
@close="closeVideoPlayer"
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -537,4 +567,5 @@ onMounted(() => {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 42 KiB |
Loading…
Reference in New Issue