前言
在视频类网站和应用中,如何实现视频间的无缝切换一直是提升用户体验的关键。本文将带你实现一个支持预加载、进度保持和丝滑过渡的视频切换组件,解决视频播放中的卡顿问题。
一、需求分析与设计思路
核心需求
- 预加载机制:提前加载下一个视频
- 进度保持:切换时保留播放进度
- 无缝过渡:视频间平滑切换效果
- 内存管理:及时清理不用的视频元素
技术选型
- 使用Class封装核心逻辑
- 私有字段管理内部状态
- DOM操作实现视频切换
- 预加载优化体验
二、核心实现解析
export default class SwitchVideo {
// 私有字段
#videoNames; // 视频名称列表
#nextVideo = null; // 预加载的视频元素
#container = null; // 视频容器
// 公共字段
index = 0; // 当前视频索引
currentVideo = null; // 当前播放视频
currentTime = 0; // 当前播放时间,可以指定视频初始化的时间
constructor(videoNames, videoId, index = 0, currentTime = 0) {
this.#videoNames = videoNames;
this.index = index;
this.currentTime = currentTime;
this.#container = document.getElementById(videoId);
this.#preloadNextVideo(); // 初始化预加载
}
// 预加载下一个视频(私有方法)
#preloadNextVideo() {
if (this.#nextVideo) return;
this.#nextVideo = document.createElement('video');
this.#nextVideo.src = `./video/${this.#videoNames[this.index]}`;
this.#nextVideo.preload = 'auto';
this.#nextVideo.muted = true;
this.#nextVideo.style.display = 'none';
// 保持播放进度
this.#nextVideo.currentTime = this.currentTime;
this.currentTime = 0; // 重置进度
this.#container.appendChild(this.#nextVideo);
this.#nextVideo.oncanplaythrough = () => {
console.log('视频预加载完成:', this.#videoNames[this.index]);
};
}
// 执行视频切换
getVideo() {
if (!this.#nextVideo) {
this.#preloadNextVideo();
return;
}
// 显示新视频并播放
this.#nextVideo.style.display = 'block';
this.#nextVideo.autoplay = true;
this.#nextVideo.play();
// 移除旧视频(带淡出效果)
if (this.currentVideo) {
this.currentVideo.style.opacity = '0';
this.#container.removeChild(this.currentVideo);
}
// 更新状态
this.currentVideo = this.#nextVideo;
this.index = (this.index + 1) % this.#videoNames.length;
this.#nextVideo = null;
// 预加载下一个视频
this.#preloadNextVideo();
}
}
三、关键技术创新点
1. 双缓冲预加载机制
// 始终保持两个视频元素:
// - currentVideo: 当前播放
// - #nextVideo: 预加载的下一个
2. 播放进度保持
// 切换时保存当前时间
this.#nextVideo.currentTime = this.currentTime;
// 播放新视频后重置
this.currentTime = 0;
四、完整使用示例
// 1. 初始化
const switcher = new SwitchVideo(
['video1.mp4', 'video2.mp4', 'video3.mp4'],
'video-container',
0, // 初始索引
10 // 初始播放时间(秒)
);
//上来就调用一次,保证初始化时有视频播放
switcher.getVideo();
// 2. 添加控制按钮
document.getElementById('next-btn').addEventListener('click', () => {
switcher.getVideo();
});