如何在 Video.js 中为多个视频独立控制进度条的显示与隐藏
发布时间 - 2025-12-30 00:00:00 点击率:次本文详解如何使用 video.js 为不同视频(如 video1/video2)维护独立状态,实现在播放完成(100%)后才显示进度条,并避免变量作用域与事件绑定逻辑错误。
在 Video.js 中动态控制进度条(progressControl)的显隐,关键在于:状态需持久化、事件监听需正确绑定、且每个视频的状态必须相互隔离。你原始代码的核心问题并非语法错误,而是逻辑结构缺陷——video1 和 video2 被定义为函数局部变量,每次调用 light(Cvideo) 都会重新初始化为 false,导致 video1 = true 的赋值永远无法跨调用保留,自然无法触发后续的 show() 分支。
✅ 正确方案:使用闭包或外部状态管理
推荐将视频状态提升至全局作用域(或模块级),确保状态在多次调用间持续有效:
// 全局状态对象 —— 每个视频 ID 对应独立布尔标记
const videoStates = {
1: false,
2: false
};
function light(Cvideo) {
const player = videojs("videoP");
const videoSrc = Cvideo === 1
? "video/1.mp4"
: "video/2.mp4";
// 更新视频标题(可选)
document.getElementById("nameV").textContent = Cvideo;
// 重置进度显示
document.getElementById("percentage").textContent = "0%";
// 根据当前视频 ID 判断是否已播放完成过
if (vid
eoStates[Cvideo]) {
player.controlBar.progressControl.show();
} else {
player.controlBar.progressControl.hide();
// 绑定一次 timeupdate 监听器(防重复绑定!)
const handleTimeUpdate = () => {
const currentTime = player.currentTime();
const duration = player.duration();
if (duration && !isNaN(duration)) { // 确保 duration 可用
const percentage = Math.round((currentTime / duration) * 100);
document.getElementById("percentage").textContent = `${percentage}%`;
if (percentage >= 99.9) { // 使用 >= 99.9 更鲁棒(浮点精度问题)
videoStates[Cvideo] = true;
player.controlBar.progressControl.show();
player.off("timeupdate", handleTimeUpdate); // ✅ 移除监听,避免内存泄漏
}
}
};
player.on("timeupdate", handleTimeUpdate);
}
// 加载并播放新视频
player.src({ type: "video/mp4", src: videoSrc });
player.play();
}⚠️ 关键注意事项
- 避免重复绑定事件:每次调用 light() 都新增 timeupdate 监听器会导致多个监听器累积,引发性能问题和逻辑混乱。务必在满足条件后调用 player.off() 清理。
- duration() 异步性:player.duration() 在元数据加载完成前可能返回 NaN 或 0,务必加 if (duration && !isNaN(duration)) 安全判断。
- 100% 判定要宽容:由于浮点计算误差,percentage === 100 很难精确命中,建议改用 percentage >= 99.9。
-
CDN 资源引用:确保在 HTML 中正确引入 Video.js CSS 与 JS(版本建议 ≥7.20):
? 扩展建议(进阶)
若项目规模扩大,推荐封装为类或使用现代模块系统(ESM)管理状态:
class VideoProgressManager {
constructor(playerId) {
this.player = videojs(playerId);
this.states = new Map(); // Map
}
showOnComplete(videoId, src) {
if (this.states.get(videoId)) {
this.player.controlBar.progressControl.show();
} else {
this.player.controlBar.progressControl.hide();
const onTimeUpdate = () => { /* ... 同上逻辑 ... */ };
this.player.on("timeupdate", onTimeUpdate);
// 记得在完成时 this.states.set(videoId, true)
}
this.player.src({ type: "video/mp4", src });
}
} 通过合理管理状态生命周期与事件绑定时机,即可实现多视频间完全独立的进度条行为控制——既符合用户体验(首次播放隐藏干扰项),又保障逻辑健壮性。
# css
# html
# js
# cdn
# 作用域
# .net
# if
# 封装
# 局部变量
# 变量作用域
# 闭包
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
大型企业网站制作流程,做网站需要注册公司吗?
如何在Windows 2008云服务器安全搭建网站?
Laravel定时任务怎么设置_Laravel Crontab调度器配置
如何在局域网内绑定自建网站域名?
北京网站制作的公司有哪些,北京白云观官方网站?
米侠浏览器网页图片不显示怎么办 米侠图片加载修复
极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?
C++时间戳转换成日期时间的步骤和示例代码
Win11怎样安装网易有道词典_Win11安装词典教程【步骤】
Win11怎么关闭专注助手 Win11关闭免打扰模式设置【操作】
图册素材网站设计制作软件,图册的导出方式有几种?
专业企业网站设计制作公司,如何理解商贸企业的统一配送和分销网络建设?
悟空浏览器如何设置小说背景色_悟空浏览器背景色设置【方法】
Laravel如何与Pusher实现实时通信?(WebSocket示例)
如何有效防御Web建站篡改攻击?
Laravel如何为API编写文档_Laravel API文档生成与维护方法
Laravel怎么调用外部API_Laravel Http Client客户端使用
宙斯浏览器文件分类查看教程 快速筛选视频文档与图片方法
谷歌Google入口永久地址_Google搜索引擎官网首页永久入口
Laravel Asset编译怎么配置_Laravel Vite前端构建工具使用
如何在 Telegram Web View(iOS)中防止键盘遮挡底部输入框
JavaScript如何操作视频_媒体API怎么控制播放
如何注册花生壳免费域名并搭建个人网站?
如何快速上传建站程序避免常见错误?
Laravel怎么连接多个数据库_Laravel多数据库连接配置
网站制作免费,什么网站能看正片电影?
千库网官网入口推荐 千库网设计创意平台入口
Laravel怎么实现模型属性的自动加密
焦点电影公司作品,电影焦点结局是什么?
Laravel如何编写单元测试和功能测试?(PHPUnit示例)
Laravel如何实现多语言支持_Laravel本地化与国际化(i18n)配置教程
如何制作公司的网站链接,公司想做一个网站,一般需要花多少钱?
如何基于PHP生成高效IDC网络公司建站源码?
零服务器AI建站解决方案:快速部署与云端平台低成本实践
google浏览器怎么清理缓存_谷歌浏览器清除缓存加速详细步骤
Windows10怎样连接蓝牙设备_Windows10蓝牙连接步骤【教程】
湖南网站制作公司,湖南上善若水科技有限公司做什么的?
Laravel如何实现图片防盗链功能_Laravel中间件验证Referer来源请求【方案】
如何用西部建站助手快速创建专业网站?
logo在线制作免费网站在线制作好吗,DW网页制作时,如何在网页标题前加上logo?
1688铺货到淘宝怎么操作 1688一键铺货到自己店铺详细步骤
JavaScript如何实现音频处理_Web Audio API如何工作?
用yum安装MySQLdb模块的步骤方法
高防服务器租用首荐平台,企业级优惠套餐快速部署
香港服务器网站测试全流程:性能评估、SEO加载与移动适配优化
如何在HTML表单中获取用户输入并结合JavaScript动态控制复利计算循环
如何快速生成凡客建站的专业级图册?
如何在自有机房高效搭建专业网站?
Laravel如何使用缓存系统提升性能_Laravel缓存驱动和应用优化方案
如何在万网自助建站平台快速创建网站?


eoStates[Cvideo]) {
player.controlBar.progressControl.show();
} else {
player.controlBar.progressControl.hide();
// 绑定一次 timeupdate 监听器(防重复绑定!)
const handleTimeUpdate = () => {
const currentTime = player.currentTime();
const duration = player.duration();
if (duration && !isNaN(duration)) { // 确保 duration 可用
const percentage = Math.round((currentTime / duration) * 100);
document.getElementById("percentage").textContent = `${percentage}%`;
if (percentage >= 99.9) { // 使用 >= 99.9 更鲁棒(浮点精度问题)
videoStates[Cvideo] = true;
player.controlBar.progressControl.show();
player.off("timeupdate", handleTimeUpdate); // ✅ 移除监听,避免内存泄漏
}
}
};
player.on("timeupdate", handleTimeUpdate);
}
// 加载并播放新视频
player.src({ type: "video/mp4", src: videoSrc });
player.play();
}