爱简收旧衣按件回收前端代码仓库
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.
 
 
 
 

230 lines
5.5 KiB

<template>
<view class="banner" :style="{ height: height }">
<swiper
:indicator-dots="false"
:autoplay="true"
:interval="3000"
:duration="500"
circular
:style="{ width: '100%', height: height }"
>
<swiper-item v-for="(item, index) in bannerList" :key="item.id || index">
<view v-if="item.type == 1" class="video-container">
<!-- 预览状态:显示封面图 -->
<image
v-if="!videoPlayingStates[index]"
:src="item.image || ''"
mode="aspectFill"
style="width: 100%; height: 100%;"
class="video-poster"
@click="playVideoFullscreen(item, index)"
/>
<!-- 播放状态:显示视频 -->
<video
v-else
:id="`${videoIdPrefix}-${index}`"
:src="item.voUrl"
:autoplay="true"
:muted="false"
:loop="false"
:controls="true"
:show-play-btn="true"
:show-center-play-btn="false"
:show-fullscreen-btn="true"
:show-progress="true"
:show-mute-btn="true"
:enable-progress-gesture="true"
:enable-play-gesture="true"
object-fit="cover"
style="width: 100%; height: 100%;"
@fullscreenchange="onFullscreenChange"
@play="onVideoPlay(index)"
@pause="onVideoPause(index)"
@ended="onVideoEnded(index)"
></video>
<!-- 播放按钮覆盖层 -->
<view v-if="!videoPlayingStates[index]" class="video-overlay" @click="playVideoFullscreen(item, index)">
<view class="play-button-large">
<view class="play-triangle"></view>
</view>
</view>
</view>
<image v-else :src="item.image" mode="aspectFill" style="width: 100%; height: 100%;" @click="onImageClick(item, index)" />
</swiper-item>
</swiper>
<!-- 备用静态图片当没有轮播图数据时显示 -->
<image v-if="!bannerList || bannerList.length === 0" :src="fallbackImage" mode="aspectFill" style="width: 100%; height: 100%;" />
</view>
</template>
<script>
export default {
name: 'BannerSwiper',
props: {
// 轮播图数据
bannerList: {
type: Array,
default: () => []
},
// 轮播图高度
height: {
type: String,
default: '400rpx'
},
// 备用图片
fallbackImage: {
type: String,
default: ''
},
// 视频ID前缀,用于区分不同页面的视频
videoIdPrefix: {
type: String,
default: 'video'
}
},
data() {
return {
videoPlayingStates: {} // 记录每个视频的播放状态
}
},
methods: {
// 视频全屏播放
playVideoFullscreen(item, index) {
if (!this.videoPlayingStates[index]) {
// 第一次点击:显示视频并开始播放
this.$set(this.videoPlayingStates, index, true)
// 等待视频元素渲染后再进行操作
this.$nextTick(() => {
setTimeout(() => {
const videoContext = uni.createVideoContext(`${this.videoIdPrefix}-${index}`, this)
if (videoContext) {
// 直接进入全屏播放,强制竖屏
videoContext.requestFullScreen({
direction: 0 // 竖屏方向,0代表竖屏,1代表横屏,-1自动
})
}
}, 200)
})
}
},
// 图片点击事件
onImageClick(item, index) {
this.$emit('image-click', { item, index })
},
// 视频播放事件
onVideoPlay(index) {
this.$set(this.videoPlayingStates, index, true)
},
// 视频暂停事件
onVideoPause(index) {
this.$set(this.videoPlayingStates, index, false)
},
// 视频结束事件
onVideoEnded(index) {
// 视频播放结束,回到预览状态
this.$set(this.videoPlayingStates, index, false)
},
// 全屏状态改变事件
onFullscreenChange(e) {
console.log('全屏状态改变:', e.detail)
const videoIndex = e.target.id.replace(`${this.videoIdPrefix}-`, '')
if (e.detail.fullScreen) {
// 进入全屏时,不做任何操作
console.log('进入全屏模式,方向:', e.detail.direction)
} else {
// 退出全屏时,回到预览状态
console.log('退出全屏模式,回到预览状态')
this.$set(this.videoPlayingStates, videoIndex, false)
}
}
}
}
</script>
<style lang="scss" scoped>
.banner {
width: 100%;
position: relative;
overflow: hidden;
border-radius: 0 0 30rpx 30rpx;
image {
width: 100%;
height: 100%;
}
.video-container {
position: relative;
width: 100%;
height: 100%;
.video-poster {
cursor: pointer;
transition: transform 0.2s ease;
&:active {
transform: scale(0.98);
}
}
.video-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.4);
z-index: 10;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
.play-button-large {
width: 120rpx;
height: 120rpx;
background: transparent;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
backdrop-filter: blur(10rpx);
transition: all 0.3s ease;
box-shadow: 0 8rpx 30rpx rgba(0, 0, 0, 0.3);
&:active {
transform: scale(0.9);
background: rgba(255, 255, 255, 0.1);
}
.play-triangle {
width: 0;
height: 0;
border-left: 24rpx solid #fff;
border-top: 18rpx solid transparent;
border-bottom: 18rpx solid transparent;
margin-left: 8rpx;
transition: all 0.3s ease;
filter: drop-shadow(0 2rpx 4rpx rgba(0, 0, 0, 0.3));
}
}
&:hover .play-button-large {
transform: scale(1.1);
box-shadow: 0 12rpx 40rpx rgba(0, 0, 0, 0.4);
.play-triangle {
border-left-color: #ff8917;
}
}
}
}
}
</style>