视频缓冲loading的可靠判断依据是waiting事件配合!video.paused,恢复播放以playing事件为准;buffered需用end(0)/duration算进度,safari需降级处理;loading显隐应脱离window.onload,用load()后立即显示、playing或error时隐藏,并设8秒超时兜底。

视频加载时的 loading 效果,不能靠 readyState 判断是否“正在缓冲”,也不能等 loadeddata 才显示——用户早卡住了。真正可用的信号只有 waiting 事件配合播放状态,再叠加 buffered 做进度估算。
video 元素触发 waiting 事件才是“缓冲中”的可靠标志
浏览器在播放过程中因数据不足自动暂停时,会同步触发 waiting,且此时 video.paused === false。这是唯一能区分“用户主动暂停”和“被迫缓冲”的依据。
- 仅监听
waiting不够:如果用户点了暂停再点播放,也会触发该事件,但不该显示 loading - 必须加判断
!video.paused,否则会在暂停状态下误显 loading -
canplay或canplaythrough只表示“可以播”,不代表后续不卡;playing才是缓冲结束、恢复播放的准确信号 - 别用
timeupdate频繁轮询 currentTime 和 buffered 来“猜”是否卡住——开销大、不准、Safari 下尤其不可靠
用 buffered 属性画缓冲进度条,但别直接读 .length
video.buffered 是 TimeRanges 对象,不是数组,.length 返回的是已缓存区段数量(通常为 1),不是字节或百分比。想算“已缓到哪了”,得取第一个区段的结束时间。
- 先确保
video.duration已知:监听loadedmetadata后才能安全计算比例 - 用
video.buffered.end(0)获取首个连续缓冲区的结束时间(多数场景够用) - 公式:
Math.min(1, buffered.end(0) / video.duration),结果转成百分比更新进度条宽度 - Safari 常返回空
buffered或不更新,建议 fallback 到“显示旋转 loading + 文字提示”,不强求进度条动
loading UI 显隐逻辑必须脱离 window.onload
用 window.addEventListener('load', hideLoading) 会等到所有图片、字体、第三方脚本加载完才收起 loading,用户早就看到视频画面甚至播了几秒了。
- loading 元素应写在
开头,带position: fixed和z-index,避免被遮挡 - 显示时机:在
video.load()或设置src后立刻showLoading(),不要等任何事件 - 隐藏时机:监听
playing事件(非canplay),并在error事件里也调用hideLoading()防止卡死 - 加 8 秒超时兜底:
setTimeout(hideLoading, 8000),避免因资源异常导致 loading 永不消失
纯 CSS spinner 在 Safari 上要加硬件加速修复
只写 animation: spin 1s linear infinite 和 transform: rotate(),在 iOS 15–16 的 Safari 中容易掉帧或白屏几帧。
- 必须加
transform-style: preserve-3d和backface-visibility: hidden触发 GPU 加速 -
border-radius: 50%缺一不可,否则转的是方框不是圆环 - 动画定义必须内联在
<style></style>里,外链 CSS 加载延迟会导致首帧空白 - 别用
will-change: transform,旧 iPad 等低内存设备反而卡顿
最易被忽略的一点:视频 loading 不是“等资源下载完”,而是“等下一帧数据就绪”。所以所有判断都得围绕播放行为本身,而不是网络或 DOM 生命周期。一旦把 waiting 当成普通事件随便监听,就等于放弃了对真实卡顿的响应能力。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











