H5页面多个视频如何只同时播放一个?
目录
- 背景
- 1. 首先介绍下 muted 属性
- 2. 监听播放和暂停操作
- 3. 视频播放完毕后返回桌面,再进入H5页面发现视频封面丢失置灰
- 解决思路:
背景
页面模块同时有个四个视频模块,发现可以同时播放四个视频,但是理想的是每次只播放一个。
旧代码:
<div class="list-item" v-for="item of VIDEO_TYPES" :key="item.title">
<video
ref="videosRef"
class="video"
playsinline
muted
webkit-playsinline
preload="auto"
x5-video-player-type="h5-page"
controls
:poster="item.poster"
:src="item.video"
></video>
</div>
1. 首先介绍下 muted 属性
一个布尔属性,指明在视频中音频的默认设置。设置后,音频会初始化为静音。默认值是 false, 意味着视频播放的时候音频也会播放。
视频静音的情况下,IOS 可以同时播放多个,所以把这个属性去掉,IOS 每次就只能播放一个了,但是 Android 比较特殊,即使去到这个属性也还是可以同时播放多个视频。
2. 监听播放和暂停操作
在每次点击播放的时候,先停止所有视频,然后在播放正在点击的视频。
<div class="list-item" v-for="item of VIDEO_TYPES" :key="item.title">
<video
ref="videosRef"
class="video"
playsinline
webkit-playsinline
preload="auto"
x5-video-player-type="h5-page"
controls
:poster="item.poster"
:src="item.video"
@play="onPlay(item.video)"
@pause="onPause(item.video)"
></video>
<div class="title">{{ item.title }}</div>
</div>
const activeVideoId = ref('');
const onPlay = (videoId) => {
if (isIOS) return; // IOS不需要处理,不然会有点击的卡顿感
// 如果已有视频在播放,暂停它
if (activeVideoId.value && activeVideoId.value !== videoId) {
const activeVideo = videosRef.value.find((video) => {
return video.src === activeVideoId.value;
});
if (activeVideo) {
activeVideo.pause();
}
}
activeVideoId.value = videoId; // 设置当前播放的视频
};
// 视频暂停时触发
const onPause = (videoId) => {
if (isIOS) return;
if (activeVideoId.value === videoId) {
activeVideoId.value = null; // 清除当前播放的视频 ID
}
};
3. 视频播放完毕后返回桌面,再进入H5页面发现视频封面丢失置灰
可能原因:
当你退出视频播放页面(例如最小化到桌面),浏览器可能会暂停页面的 JavaScript 执行或丢失某些页面状态。导致重新进入页面时,视频封面未被正确恢复。
解决思路:
确保封面重新加载:
在页面重新进入时,强制重新加载封面图像。你可以通过监听 visibilitychange 事件或使用 onfocus 事件来确保封面图像的状态恢复。
const refreshVideo = () => {
const videos = document.querySelectorAll('video');
// 遍历每个 video 元素
videos.forEach((video) => {
const src = video.getAttribute('src');
const wasPlaying = !video.paused;
video.setAttribute('src', '');
video.setAttribute('src', src);
if (wasPlaying) {
video.play();
} else {
// 重新加载视频
video.load();
}
});
};
onMounted(() => {
document.addEventListener('visibilitychange', refreshVideo);
});
onBeforeMount(() => {
document.removeEventListener('visibilitychange', refreshVideo);
});