mrr.sj.front/pages/album/components/videoSlide.nvue

822 lines
26 KiB
Plaintext
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 style="z-index: 100;">
<!-- 视频滑动主容器 -->
<view class="view-box" :style="viewTopLength">
<!-- 复用的5个视频容器 - 核心复用节点,不可删减 -->
<view class="video-box" :style="itemViewTopLength0">
<video :src="videoInfo_0.src" :style="fillScreen" :autoplay="videoInfo_0.autoplay"
:loop="videoInfo_0.loop" :controls="videoInfo_0.controls"
:enable-play-gesture="videoInfo_0.enablePlayGesture" :objectFit="videoInfo_0.objectFit || objectFit"
:show-fullscreen-btn="videoInfo_0.showFullscreenBtn"
:enable-progress-gesture="videoInfo_0.enableProgressGesture" @timeupdate="timeupdate(0,$event)"
@ended='ended' :show-play-btn="videoInfo_0.showPlayBtn" :show-progress="videoInfo_0.showProgress"
initial-time="0" id='video_id_0' @play="playing(0)" :muted="videoInfo_0.isMuted"
webkit-playsinline="true" playsinline="true">
</video>
<cover-view v-if="!videoInfo_0.flag" :style="stopIcon" class="cover-view-stop" />
<cover-view v-if="cover && videoInfo_0.coverStatus" :style="fillScreen2" class="video-image">
<image :mode="videoInfo_0.mode || mode" :src="videoInfo_0.coverUrl" :style="fillScreen"></image>
</cover-view>
<view class="video-action" @touchstart.stop='videotouchstart' @touchmove.stop="videotochmove"
@touchend.stop='videotouchend' @click.stop="videoClick"></view>
<!-- 视频文本区域 - 每个视频都有 -->
<view class="video-texts">
<view class="flex-row-center" style="flex: 1;">
<text class="video-title">{{ videoInfo_0.src }}</text>
<text class="video-score">评分 4.8</text>
</view>
<view class="flex-row-center-between" style="flex: 1;">
<text class="video-text">{{videoInfo_0.name}}</text>
<!-- 声音图标 - 绑定0号视频的状态点击切换静音 -->
<image class="video-sound"
:src="videoInfo_0.isMuted ? '/static/images/icons/sound_no.png' : '/static/images/icons/sound_yes.png'"
@click.stop="toggleMute(0)"></image>
</view>
</view>
</view>
<view class="video-box" :style="itemViewTopLength1">
<video :src="videoInfo_1.src" :style="fillScreen" :autoplay="videoInfo_1.autoplay"
:loop="videoInfo_1.loop" :controls="videoInfo_1.controls"
:enable-play-gesture="videoInfo_1.enablePlayGesture" :objectFit="videoInfo_1.objectFit || objectFit"
:show-fullscreen-btn="videoInfo_1.showFullscreenBtn"
:enable-progress-gesture="videoInfo_1.enableProgressGesture" @timeupdate="timeupdate(1,$event)"
@ended='ended' :show-play-btn="videoInfo_1.showPlayBtn" :show-progress="videoInfo_1.showProgress"
initial-time="0" id='video_id_1' @play="playing(1)" :muted="videoInfo_1.isMuted"
webkit-playsinline="true" playsinline="true">
</video>
<cover-view v-if="!videoInfo_1.flag" :style="stopIcon" class="cover-view-stop" />
<cover-view v-if="cover && videoInfo_1.coverStatus" :style="fillScreen2" class="video-image">
<image :mode="videoInfo_1.mode || mode" :src="videoInfo_1.coverUrl" :style="fillScreen"></image>
</cover-view>
<view class="video-action" @touchstart='videotouchstart' @touchmove="videotochmove"
@touchend='videotouchend' @click="videoClick"></view>
<!-- 视频文本区域 - 1号视频 -->
<view class="video-texts">
<view class="flex-row-center" style="flex: 1;">
<text class="video-title">珍草品汇理疗馆珍馆服务流程11订单</text>
<text class="video-score">评分 4.8</text>
</view>
<view class="flex-row-center-between" style="flex: 1;">
<text class="video-text">{{videoInfo_1.name}}</text>
<!-- 声音图标 - 绑定1号视频的状态 -->
<image class="video-sound"
:src="videoInfo_1.isMuted ? '/static/images/icons/sound_no.png' : '/static/images/icons/sound_yes.png'"
@click.stop="toggleMute(1)"></image>
</view>
</view>
</view>
<view class="video-box" :style="itemViewTopLength2">
<video :src="videoInfo_2.src" :style="fillScreen" :autoplay="videoInfo_2.autoplay"
:loop="videoInfo_2.loop" :controls="videoInfo_2.controls"
:enable-play-gesture="videoInfo_2.enablePlayGesture" :objectFit="videoInfo_2.objectFit || objectFit"
:show-fullscreen-btn="videoInfo_2.showFullscreenBtn"
:enable-progress-gesture="videoInfo_2.enableProgressGesture" @timeupdate="timeupdate(2,$event)"
@ended='ended' :show-play-btn="videoInfo_2.showPlayBtn" :show-progress="videoInfo_2.showProgress"
initial-time="0" id='video_id_2' @play="playing(2)" :muted="videoInfo_2.isMuted"
webkit-playsinline="true" playsinline="true">
</video>
<cover-view v-if="!videoInfo_2.flag" :style="stopIcon" class="cover-view-stop" />
<cover-view v-if="cover && videoInfo_2.coverStatus" :style="fillScreen2" class="video-image">
<image :mode="videoInfo_2.mode || mode" :src="videoInfo_2.coverUrl" :style="fillScreen"></image>
</cover-view>
<view class="video-action" @touchstart='videotouchstart' @touchmove="videotochmove"
@touchend='videotouchend' @click="videoClick"></view>
<!-- 视频文本区域 - 2号视频 -->
<view class="video-texts">
<view class="flex-row-center" style="flex: 1;">
<text class="video-title">珍草品汇理疗馆珍馆服务流程11订单</text>
<text class="video-score">评分 4.8</text>
</view>
<view class="flex-row-center-between" style="flex: 1;">
<text class="video-text">{{videoInfo_2.name}}</text>
<!-- 声音图标 - 绑定2号视频的状态 -->
<image class="video-sound"
:src="videoInfo_2.isMuted ? '/static/images/icons/sound_no.png' : '/static/images/icons/sound_yes.png'"
@click.stop="toggleMute(2)"></image>
</view>
</view>
</view>
<view class="video-box" :style="itemViewTopLength3">
<video :src="videoInfo_3.src" :style="fillScreen" :autoplay="videoInfo_3.autoplay"
:loop="videoInfo_3.loop" :controls="videoInfo_3.controls"
:enable-play-gesture="videoInfo_3.enablePlayGesture" :objectFit="videoInfo_3.objectFit || objectFit"
:show-fullscreen-btn="videoInfo_3.showFullscreenBtn"
:enable-progress-gesture="videoInfo_3.enableProgressGesture" @timeupdate="timeupdate(3,$event)"
@ended='ended' :show-play-btn="videoInfo_3.showPlayBtn" :show-progress="videoInfo_3.showProgress"
initial-time="0" id='video_id_3' @play="playing(3)" :muted="videoInfo_3.isMuted"
webkit-playsinline="true" playsinline="true">
</video>
<cover-view v-if="!videoInfo_3.flag" :style="stopIcon" class="cover-view-stop" />
<cover-view v-if="cover && videoInfo_3.coverStatus" :style="fillScreen2" class="video-image">
<image :mode="videoInfo_3.mode || mode" :src="videoInfo_3.coverUrl" :style="fillScreen"></image>
</cover-view>
<view class="video-action" @touchstart='videotouchstart' @touchmove="videotochmove"
@touchend='videotouchend' @click="videoClick"></view>
<!-- 视频文本区域 - 3号视频 -->
<view class="video-texts">
<view class="flex-row-center" style="flex: 1;">
<text class="video-title">珍草品汇理疗馆珍馆服务流程11订单</text>
<text class="video-score">评分 4.8</text>
</view>
<view class="flex-row-center-between" style="flex: 1;">
<text class="video-text">{{videoInfo_3.name}}</text>
<!-- 声音图标 - 绑定3号视频的状态 -->
<image class="video-sound"
:src="videoInfo_3.isMuted ? '/static/images/icons/sound_no.png' : '/static/images/icons/sound_yes.png'"
@click.stop="toggleMute(3)"></image>
</view>
</view>
</view>
<view class="video-box" :style="itemViewTopLength4">
<video :src="videoInfo_4.src" :style="fillScreen" :autoplay="videoInfo_4.autoplay"
:loop="videoInfo_4.loop" :controls="videoInfo_4.controls"
:enable-play-gesture="videoInfo_4.enablePlayGesture" :objectFit="videoInfo_4.objectFit || objectFit"
:show-fullscreen-btn="videoInfo_4.showFullscreenBtn"
:enable-progress-gesture="videoInfo_4.enableProgressGesture" @timeupdate="timeupdate(4,$event)"
@ended='ended' :show-play-btn="videoInfo_4.showPlayBtn" :show-progress="videoInfo_4.showProgress"
initial-time="0" id='video_id_4' @play="playing(4)" :muted="videoInfo_4.isMuted"
webkit-playsinline="true" playsinline="true">
</video>
<cover-view v-if="!videoInfo_4.flag" :style="stopIcon" class="cover-view-stop" />
<cover-view v-if="cover && videoInfo_4.coverStatus" :style="fillScreen2" class="video-image">
<image :mode="videoInfo_4.mode || mode" :src="videoInfo_4.coverUrl" :style="fillScreen"></image>
</cover-view>
<view class="video-action" @touchstart='videotouchstart' @touchmove="videotochmove"
@touchend='videotouchend' @click="videoClick"></view>
<!-- 视频文本区域 - 4号视频 -->
<view class="video-texts">
<view class="flex-row-center" style="flex: 1;">
<text class="video-title">珍草品汇理疗馆珍馆服务流程11订单</text>
<text class="video-score">评分 4.8</text>
</view>
<view class="flex-row-center-between" style="flex: 1;">
<text class="video-text">{{videoInfo_4.name}}</text>
<!-- 声音图标 - 绑定4号视频的状态 -->
<image class="video-sound"
:src="videoInfo_4.isMuted ? '/static/images/icons/sound_no.png' : '/static/images/icons/sound_yes.png'"
@click.stop="toggleMute(4)"></image>
</view>
</view>
</view>
<view @touchend='progressTouchend' class="progress-view">
<uv-slider v-if="showSlider" v-model="progressValue" activeColor="#D8D8D8" block-size="6"
backgroundColor="#494949;" class="progress-slider"></uv-slider>
</view>
<!-- 修改Dot指示器 - 最多显示5个 -->
<view class="dots" :style="{top:`${0.5*winHeight}px`}" v-if="videoListLength > 1">
<view class="dots-container">
<view class="dot-item" v-for="(dotIndex, idx) in visibleDots" :key="idx"
:class="{ active: dotIndex === videoIndex }" @click="jumpToVideo(dotIndex)"></view>
</view>
<text class="pageNumber">
{{ videoIndex+1 }}/{{ videoListLength }}
</text>
</view>
</view>
</view>
</template>
<script>
let VIDEO_LIST = []
let initVideoInfo = {
src: "",
coverStatus: true,
coverUrl: "",
flag: false,
objectFit: "",
mode: "",
isMuted: false, // 默认不静音
autoplay: false,
loop: true,
controls: false,
enablePlayGesture: true,
showFullscreenBtn: false,
enableProgressGesture: false,
showPlayBtn: false,
showProgress: false
}
export default {
props: {
popVideoList: {
type: Array,
default: [] // 默认值设为空数组JSON避免parse报错
},
marginTop: {
type: String,
default: "88" // 默认值设为空数组JSON避免parse报错
}
},
data() {
return {
playSetTime:null,
showSlider: true,
progressTime: 0,
progressValue: 0,
boxHeight: 0,
objectFit: "fill",
mode: "scaleToFill",
winWidth: 1,
winHeight: 1,
videoIndex: 0,
viewTop: 0,
viewTopPostion: 0,
videoList: [],
videoListLength: 0,
itemViewTop0: 0,
itemViewTop1: 0,
itemViewTop2: 0,
itemViewTop3: 0,
itemViewTop4: 0,
videoInfo_0: initVideoInfo,
videoInfo_1: initVideoInfo,
videoInfo_2: initVideoInfo,
videoInfo_3: initVideoInfo,
videoInfo_4: initVideoInfo,
stopIcon: '',
videotouchstartTimestamp: 0,
videotouchendTimestamp: 0,
moveView: true,
cover: true,
slidingStatus: false,
videoPlayingStatus: false,
preloadedIndex: [],
startPageY: 0,
endPageY: 0,
// 新增控制可视dot的数组
visibleDots: [],
};
},
watch: {
// videoList: {
// handler(newVal, oldVal) {
// },
// immediate: true, // 可选:组件初始化时立即执行一次(即使值未变化)
// deep: false // 普通类型无需深度监听默认false
// }
},
created(options) {
//#ifdef APP-PLUS
plus.screen.lockOrientation("portrait-primary")
//#endif
if (this.popVideoList.length) {
try {
VIDEO_LIST = []
this.popVideoList.forEach((item, index) => {
let obj = {
"src": "",
"coverStatus": true,
"coverUrl": "",
"flag": false,
"objectFit": "contain",
"mode": "aspectFit",
"isMuted": false, // 默认不静音
"autoplay": false,
"loop": true,
"controls": false,
"enablePlayGesture": true,
"showFullscreenBtn": false,
"enableProgressGesture": false,
"showPlayBtn": false,
"showProgress": false,
"name": ""
}
obj.name = item.name
obj.src = item.url
obj.coverUrl = item.url +
`?x-oss-process=video/snapshot,t_1000,m_fast,f_jpg,w_600,ar_auto`
VIDEO_LIST.push(obj)
if (index == 0) {
initVideoInfo = obj
}
})
} catch (e) {}
this.getSystemInfo();
this.videoList = VIDEO_LIST;
this.videoListLength = this.videoList.length;
this.boxHeight = this.videoListLength * this.winHeight;
for (let i = 0; i < 5; i++) {
if (this.videoList[i]) {
this['videoInfo_' + i] = this.videoList[i]
}
}
// 初始化可视dot范围
this.updateVisibleDots();
// setTimeout(() => {
// this.playVideo(0)
// }, 500)
}
},
onUnload() {
for (let i = 0; i < 5; i++) {
this.unloadVideo(i)
}
},
computed: {
getVideoTop() {
return uni.upx2px(this.marginTop)
},
viewTopLength() {
return `height:${this.boxHeight}px;top:${this.viewTop}px;`
},
fillScreen() {
let style = `height:${this.winHeight}px;width:${this.winWidth}px;`
return style
},
fillScreen2() {
let style = `height:auto;width:${this.winWidth}px;`
return style
},
itemViewTopLength0() {
return `height:${this.winHeight}px;top:${this.itemViewTop0}px;`
},
itemViewTopLength1() {
return `height:${this.winHeight}px;top:${this.itemViewTop1}px;`
},
itemViewTopLength2() {
return `height:${this.winHeight}px;top:${this.itemViewTop2}px;`
},
itemViewTopLength3() {
return `height:${this.winHeight}px;top:${this.itemViewTop3}px;`
},
itemViewTopLength4() {
return `height:${this.winHeight}px;top:${this.itemViewTop4}px;`
}
},
methods: {
// 新增:切换视频静音状态
toggleMute(videoNum) {
// 1. 切换数据层状态
this['videoInfo_' + videoNum].isMuted = !this['videoInfo_' + videoNum].isMuted;
// 2. 同步视频实例静音状态(恢复并完善原有注释代码,加容错)
const videoCtx = uni.createVideoContext("video_id_" + videoNum, this);
if (videoCtx) {
videoCtx.mute(this['videoInfo_' + videoNum].isMuted);
}
},
// 修改点击dot跳转 - 传真实的视频索引
jumpToVideo(targetIndex) {
if (targetIndex === this.videoIndex || this.slidingStatus) return;
this.stopVideo(this.videoIndex % 5, true);
const diff = targetIndex - this.videoIndex;
this.videoIndex = targetIndex;
this.viewTopPostion = -this.videoIndex * this.winHeight;
this.viewTop = this.viewTopPostion;
if (this.videoListLength > 5) {
this.sortItemView(diff > 0 ? -1 : 1);
}
// 更新可视dot范围
this.updateVisibleDots();
setTimeout(() => {
this.playVideo(this.videoIndex % 5);
}, 400);
},
// 核心更新可视dot范围 - 最多显示5个
updateVisibleDots() {
const maxShow = 5;
const total = this.videoListLength;
// 视频总数 ≤ 5显示全部
if (total <= maxShow) {
this.visibleDots = Array.from({
length: total
}, (_, i) => i);
return;
}
// 视频总数 > 5显示包含当前索引的5个dot
// 计算起始索引,避免越界
let start = Math.max(0, Math.min(this.videoIndex - 2, total - maxShow));
// 生成5个连续的索引
this.visibleDots = Array.from({
length: maxShow
}, (_, i) => start + i);
},
progressTouchend() {
let s = Math.round(this.progressValue / 100 * this.time)
let i = this.videoIndex % 5
uni.createVideoContext("video_id_" + i, this).seek(s)
uni.createVideoContext("video_id_" + i, this).play()
},
sliderchanging(e) {
console.log(3333, e)
},
getSystemInfo() {
var _this = this;
uni.getSystemInfo({
success: function(res) {
_this.winWidth = res.windowWidth;
_this.winHeight = res.windowHeight;
let p = uni.upx2px(150)
_this.stopIcon = `left:${(res.windowWidth - p)/2}px;top:${(res.windowHeight - p)/2}px;`
_this.itemViewTop1 = res.windowHeight
_this.itemViewTop2 = res.windowHeight * 2
_this.itemViewTop3 = res.windowHeight * 3
_this.itemViewTop4 = res.windowHeight * 4
},
})
},
unloadVideo(index) {
if (index < 0 || index >= this.videoListLength) return;
const nodeNum = index % 5;
const videoCtx = uni.createVideoContext("video_id_" + nodeNum, this);
videoCtx.stop();
this.preloadedIndex = this.preloadedIndex.filter(item => item !== index);
},
playVideo(num) {
clearTimeout(this.playSetTime)
uni.$uv.debounce(() => {
this.videoPlayingStatus = true
this["videoInfo_" + num].flag = true
let VideoContext = uni.createVideoContext("video_id_" + num, this)
this.playSetTime = setTimeout(() => {
VideoContext.play()
}, 400)
}, 30)
},
stopVideo(num, control = false) {
const videoCtx = uni.createVideoContext("video_id_" + num, this);
if (!control) {
this['videoInfo_' + num].coverStatus = true;
videoCtx.stop()
} else {
videoCtx.pause()
}
this["videoInfo_" + num].flag = false
},
nowPlayVideo() {
clearTimeout(this.playSetTime)
uni.$uv.debounce(() => {
this.videoPlayingStatus = true
this["videoInfo_" + this.videoIndex].flag = true
let VideoContext = uni.createVideoContext("video_id_" + this.videoIndex, this)
this.playSetTime = setTimeout(() => {
VideoContext.play()
}, 400)
}, 30)
},
nowStopVideo() {
const videoCtx = uni.createVideoContext("video_id_" + this.videoIndex, this);
videoCtx.pause()
this["videoInfo_" + this.videoIndex].flag = false
},
videoClick() {
let num = this.videoIndex % 5
if (this["videoInfo_" + num].flag) {
this.stopVideo(num, true)
} else {
this.playVideo(num, true)
}
},
videotouchstart(e) {
this.videotouchendTimestamp = this.videotouchstartTimestamp
this.videotouchstartTimestamp = e.timestamp
if ((this.videotouchstartTimestamp - this.videotouchendTimestamp) < 500) return
if (this.slidingStatus) return
this.startPageY = e.changedTouches[0].screenY;
},
videotochmove(e) {
if ((this.videotouchstartTimestamp - this.videotouchendTimestamp) < 500) return
if (this.slidingStatus) return
this.endPageY = e.changedTouches[0].screenY;
let sliding = this.endPageY - this.startPageY
if (sliding > 20 || sliding < -20) {
this.moveView = false
} else {
this.moveView = true
}
if (this.videoIndex == 0 && sliding > 50) {
this.viewTop = 50
} else if (this.videoIndex == this.videoListLength - 1 && sliding < 0) {
this.viewTop = this.viewTopPostion
} else {
this.viewTop = this.viewTopPostion + sliding
}
},
videotouchend(e) {
if ((this.videotouchstartTimestamp - this.videotouchendTimestamp) < 500) return
if (this.slidingStatus) return
this.moveView = true
this.endPageY = e.changedTouches[0].screenY;
let sliding = this.endPageY - this.startPageY
if ((sliding >= -40 && sliding < 0) || (sliding <= 40 && sliding > 0)) {
this.slidingStatus = true
this.videoSlidingReset(sliding)
return
}
if (sliding < -30) {
this.slidingStatus = true
if (this.videoIndex == this.videoListLength - 1) {
this.videoSlidingReset(sliding)
uni.showToast({
title: "已经到底了",
icon: "none"
})
return
}
this.moveView = false
this.videoSlidingToTop(sliding)
return
}
if (sliding > 30) {
this.slidingStatus = true
if (this.videoIndex == 0) {
this.videoSlidingReset(sliding)
return
}
this.moveView = false
this.videoSlidingToBottom(sliding)
}
},
videoSlidingReset(sliding) {
this.viewTop = this.viewTopPostion
this.slidingStatus = false
},
videoSlidingToTop(sliding) {
this.stopVideo(this.videoIndex % 5, true)
this.videoIndex++
if (this.videoListLength > 5) {
this.sortItemView(sliding)
}
this.viewTopPostion = this.viewTopPostion - this.winHeight
setTimeout(() => {
this.playVideo(this.videoIndex % 5)
}, 5)
let timer = setInterval(() => {
this.viewTop = this.viewTop - 35
if (this.viewTop < (this.viewTopPostion + 10)) {
this.viewTop = this.viewTopPostion
clearInterval(timer)
this.slidingStatus = false
this.slidingCallback()
}
}, 3)
},
videoSlidingToBottom(sliding) {
this.stopVideo(this.videoIndex % 5, true)
this.videoIndex--
if (this.videoListLength > 5) {
this.sortItemView(sliding)
}
this.viewTopPostion = this.viewTopPostion + this.winHeight
setTimeout(() => {
this.playVideo(this.videoIndex % 5)
}, 5)
let timer = setInterval(() => {
this.viewTop = this.viewTop + 35
if (this.viewTop > (this.viewTopPostion - 10)) {
this.viewTop = this.viewTopPostion
clearInterval(timer)
this.slidingStatus = false
this.slidingCallback()
}
}, 3)
},
// 修改滑动结束后更新可视dot
slidingCallback() {
this.progressValue = 0
this.updateVisibleDots();
},
//滑动组件排序
sortItemView(silding) {
// 向上滑动
if (silding < 0) {
if (this.videoIndex > 2 && this.videoIndex < this.videoListLength - 2) {
let i = (this.videoIndex - 3) % 5
this["itemViewTop" + i] = this["itemViewTop" + i] + this.winHeight * 5
this['videoInfo_' + i] = this.videoList[this.videoIndex + 2]
}
return
}
// 向下滑动
if (silding > 0) {
if (this.videoIndex > 1 && this.videoIndex < this.videoListLength - 3) {
let i = (this.videoIndex + 3) % 5
this["itemViewTop" + i] = this["itemViewTop" + i] - this.winHeight * 5
this['videoInfo_' + i] = this.videoList[this.videoIndex - 2]
}
}
},
playing(i) {
setTimeout(() => {
this['videoInfo_' + i].coverStatus = false
this.moveView = true
this.slidingStatus = false
}, 600)
},
timeupdate(i, e) {
if (this.videoPlayingStatus) {
this.slidingStatus = false
this.videoPlayingStatus = false
setTimeout(() => {
this['videoInfo_' + i].coverStatus = false
this.moveView = true
}, 200)
}
this["videoInfo_" + i].flag = true
if (e.detail.duration >= this.progressTime) {
if (this.videoIndex%5 == i) {
this.time = e.detail.duration
this.progress = e.detail.currentTime
this.progressValue = (e.detail.currentTime / e.detail.duration) * 100
}
this.showProgress = true
} else {
this.showProgress = false
}
},
ended() {
let num = this.videoIndex % 5
this["videoInfo_" + num].flag = false
this.progressValue = 0
}
}
}
</script>
<style scoped lang="less">
.view-box {
// position: fixed;
// left: 0;
// right: 0;
background-color: #000;
// z-index: 900;
}
.video-box {
position: absolute;
left: 0;
right: 0;
z-index: 2000;
}
.video-image {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
z-index: 2001;
}
.video-action {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
z-index: 2008;
}
.video-texts {
position: absolute;
left: 30rpx;
right: 30rpx;
bottom: 120rpx;
z-index: 2009; // 确保在视频上方显示
.video-title {
font-weight: 500;
font-size: 24rpx;
color: #FFFFFF;
text-align: left;
font-style: normal;
lines: 1;
max-width: 240rpx;
}
.video-score {
font-weight: 500;
font-size: 24rpx;
color: #FFFFFF;
text-align: left;
font-style: normal;
margin-left: 20rpx;
}
.video-text {
font-weight: 400;
font-size: 28rpx;
color: #FFFFFF;
text-align: left;
font-style: normal;
}
.video-sound {
width: 44rpx;
height: 42rpx;
cursor: pointer; // 点击指针,提示可点击
}
}
.cover-view-stop {
position: absolute;
z-index: 9999;
width: 150rpx;
height: 200rpx;
background-color: rgba(0, 0, 0, 0.3);
border-radius: 50%;
}
.progress-view {
z-index: 9999;
position: fixed;
left: 30rpx;
right: 30rpx;
bottom: 80rpx;
.progress-slider {}
}
// 修改Dot指示器样式 - 最多显示5个 + 过渡动画
.dots {
position: fixed;
left: 20rpx;
top: 0;
transform: translateY(-50%);
z-index: 9999;
flex-direction: row;
.dots-container {
// 限制最多显示5个超出隐藏
width: fit-content;
overflow: hidden;
margin: auto 0;
.dot-item {
width: 10rpx;
height: 10rpx;
background: #FFFFFF;
border-radius: 50%;
// 核心:过渡动画,切换更丝滑
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
cursor: pointer;
margin-bottom: 10rpx;
&.active {
width: 10rpx;
height: 30rpx;
background: #FFFFFF;
border-radius: 5rpx;
}
}
}
.pageNumber {
font-weight: bold;
font-size: 28rpx;
color: #FFFFFF;
line-height: 36rpx;
text-align: left;
font-style: normal;
margin-left: 6rpx;
}
}
.flex-row-center-between {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
}
.flex-row-start-between {
display: flex;
flex-direction: row;
align-items: flex-start;
justify-content: space-between;
}
.flex-row-center-center {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}
.flex-row-center {
display: flex;
flex-direction: row;
align-items: center;
}
.flex-row-start {
display: flex;
flex-direction: row;
align-items: flex-start;
}
.flex-row-end-between {
display: flex;
flex-direction: row;
align-items: flex-end;
justify-content: space-between;
}
</style>