HTML DOM Video played 属性(长文解析)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观
前言:视频播放的“记忆体”
在现代网页开发中,视频互动功能已成为增强用户体验的重要手段。无论是在线教育平台的进度标记,还是直播应用的回放功能,开发者都需要精准控制视频播放状态。而 HTML DOM Video played 属性 就如同视频的“记忆体”,记录着用户已观看的时间范围。本文将从基础概念到实战案例,系统解析这一属性的使用方法,帮助开发者实现更智能的视频交互逻辑。
一、HTML DOM Video played 属性的核心概念
1.1 属性定义与作用
played
是 HTML5 <video>
元素的只读属性,返回一个 TimeRanges 对象,表示视频中已经被播放的时间范围。它的作用类似于“进度记忆器”,记录用户在视频中实际观看过的连续时间段。
形象比喻:
可以想象 played
属性如同一本时间账簿,每当用户播放视频时,它就会记录下每个已播放的起止时间区间,即使用户拖动进度条或暂停播放,这些记录都会被完整保存。
1.2 TimeRanges 对象解析
TimeRanges
是浏览器内置的接口,包含以下核心方法和属性:
方法/属性 | 描述 |
---|---|
start(index) | 返回指定区间(从0开始计数)的起始时间(单位:秒) |
end(index) | 返回指定区间的结束时间(单位:秒) |
length | 返回记录的总区间数量 |
关键特性:
- 视频播放会动态更新 TimeRanges 内容,例如:
- 播放后暂停:记录当前播放的起始到当前时间
- 拖动进度条:新增对应区间的记录
- 播放后快进:原有未播放的区间会被移除
二、如何获取和解析 played 属性
2.1 基础语法与代码示例
通过 JavaScript 直接访问 <video>
元素的 played
属性:
<video id="myVideo" controls>
<source src="example.mp4" type="video/mp4">
</video>
const video = document.getElementById("myVideo");
const playedRanges = video.played;
console.log("已播放区间数量:", playedRanges.length);
console.log("第一个区间的起始时间:", playedRanges.start(0));
console.log("第一个区间的结束时间:", playedRanges.end(0));
执行结果示例:
如果用户已播放到 15 秒并暂停,控制台可能输出:
已播放区间数量: 1
第一个区间的起始时间: 0
第一个区间的结束时间: 15
2.2 动态监听播放进度
通过结合 timeupdate
事件,可以实时跟踪播放状态:
video.addEventListener("timeupdate", () => {
const currentPlayTime = video.currentTime;
const isCurrentTimePlayed = isTimeInRanges(currentPlayTime);
console.log(`当前时间 ${currentPlayTime} 秒是否已播放:`, isCurrentTimePlayed);
});
// 辅助函数:判断时间是否在已播放区间内
function isTimeInRanges(time) {
for (let i = 0; i < video.played.length; i++) {
const start = video.played.start(i);
const end = video.played.end(i);
if (time >= start && time < end) return true;
}
return false;
}
三、实际应用场景与代码实现
3.1 自定义进度条高亮显示
通过 played
属性可以实现“已观看”和“未观看”进度的可视化区分:
<div class="progress-bar">
<div class="played-portion"></div>
<div class="buffered-portion"></div>
</div>
function updateProgress() {
const duration = video.duration;
const played = video.played;
// 计算已播放总时长
let totalPlayed = 0;
for (let i = 0; i < played.length; i++) {
totalPlayed += played.end(i) - played.start(i);
}
// 更新样式(假设总进度条宽度为 300px)
const progressWidth = (totalPlayed / duration) * 300;
document.querySelector(".played-portion").style.width = `${progressWidth}px`;
}
video.addEventListener("timeupdate", updateProgress);
效果说明:
- 绿色区块(
.played-portion
)会随用户播放累积增长 - 即使用户多次暂停/快进,也能准确统计有效观看时间
3.2 触发特定时间点的交互
结合 played
属性可实现“已播放到某章节”时显示提示:
function checkChapterCompletion() {
const chapterTime = 60; // 第一章结束时间:1分钟
if (isTimeInRanges(chapterTime)) {
alert("恭喜!您已完成第一章的学习");
}
}
// 在播放结束或特定时间点触发检查
video.addEventListener("ended", checkChapterCompletion);
video.addEventListener("timeupdate", () => {
if (video.currentTime >= chapterTime) checkChapterCompletion();
});
四、关键注意事项与进阶技巧
4.1 浏览器兼容性问题
尽管现代浏览器均支持 played
属性,但需注意以下细节:
-
未加载时的空值问题:
在视频未开始加载时(如video.readyState < 1
),played.length
可能返回0
if (video.readyState >= HTMLMediaElement.HAVE_METADATA) { // 安全访问 played 属性 }
-
动态内容的影响:
当视频源动态变化(如src
属性修改)时,played
记录会被重置
4.2 性能优化建议
-
避免高频访问 TimeRanges:
timeupdate
事件可能每秒触发多次,建议通过节流函数减少计算开销let lastUpdate = 0; function throttledUpdate() { if (Date.now() - lastUpdate > 200) { updateProgress(); lastUpdate = Date.now(); } } video.addEventListener("timeupdate", throttledUpdate);
-
区分已播放与缓冲范围:
使用buffered
属性配合played
可实现更精细的进度控制const buffered = video.buffered; const bufferedEnd = buffered.end(buffered.length - 1);
五、完整案例:视频学习进度追踪系统
5.1 功能设计目标
- 实时显示已观看百分比
- 记录用户每次播放的连续区间
- 保存进度到本地存储(可选)
5.2 完整代码实现
<video id="videoPlayer" controls>
<source src="lecture.mp4" type="video/mp4">
</video>
<div id="progressInfo">已观看: 0%</div>
const video = document.getElementById("videoPlayer");
const progressInfo = document.getElementById("progressInfo");
// 初始化本地存储(如需持久化)
let savedRanges = JSON.parse(localStorage.getItem("playedRanges")) || [];
function updateProgress() {
if (video.readyState < 1) return; // 等待视频元数据加载
const currentRanges = Array.from({ length: video.played.length }, (_, i) => ({
start: video.played.start(i),
end: video.played.end(i)
}));
// 合并新旧区间(防止重复记录)
savedRanges = mergeRanges([...savedRanges, ...currentRanges]);
// 更新显示
const totalPlayed = savedRanges.reduce((sum, r) => sum + (r.end - r.start), 0);
const percentage = (totalPlayed / video.duration) * 100;
progressInfo.textContent = `已观看: ${percentage.toFixed(1)}%`;
// 保存到本地存储(可选)
localStorage.setItem("playedRanges", JSON.stringify(savedRanges));
}
// 辅助函数:合并重叠区间
function mergeRanges(ranges) {
ranges.sort((a, b) => a.start - b.start);
const merged = [];
for (const range of ranges) {
if (merged.length === 0) {
merged.push(range);
} else {
const last = merged[merged.length - 1];
if (range.start <= last.end) {
last.end = Math.max(last.end, range.end);
} else {
merged.push(range);
}
}
}
return merged;
}
video.addEventListener("timeupdate", updateProgress);
结论:掌握视频播放的“时间之眼”
通过深入理解 HTML DOM Video played 属性,开发者能够构建更智能的视频交互系统。从基础的进度显示到复杂的学习进度追踪,这一属性为开发者提供了精准的“时间之眼”,帮助用户获得更个性化的体验。在实际开发中,需注意浏览器兼容性和性能优化,结合 buffered
、currentTime
等属性,可以进一步拓展视频应用的功能边界。掌握这些技术后,您将能够更自信地应对视频类项目的开发挑战。