使用IntersectionObserver API可实现视频进入视口时自动播放、离开时暂停,需添加muted和playsinline属性并处理play() Promise拒绝情况。

当视频进入视口时自动播放、离开时暂停,这是现代网页中常见的交互需求。HTML5 <video></video> 元素配合 IntersectionObserver API 可以轻量、高效地实现这一效果,无需依赖第三方库,也避免了频繁监听 scroll 事件的性能开销。
基础结构:准备可观察的视频元素
确保视频支持静音自动播放(多数浏览器强制要求),并设置 preload="metadata" 或 "auto" 提升响应速度:
<video class="scroll-video" muted playsinline preload="metadata"><source src="example.mp4" type="video/mp4"></source></video>
关键属性说明:
-
muted:必须添加,否则自动播放会被浏览器阻止 -
playsinline:iOS Safari 中防止全屏播放 -
preload="metadata":仅加载元数据,兼顾首帧显示速度与带宽节省
用 IntersectionObserver 监听可视状态
创建观察器,设定触发阈值(如 0.1 表示视频顶部 10% 进入视口即触发):
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
const video = entry.target;
if (entry.isIntersecting) {
video.play().catch(e => console.warn("Play failed:", e));
} else {
video.pause();
}
});
}, { threshold: 0.1 });
然后遍历所有目标视频并开始观察:
document.querySelectorAll('.scroll-video').forEach(video => {
observer.observe(video);
});
注意:video.play() 返回 Promise,需处理可能的拒绝(例如用户未交互过导致策略限制),但静音视频在大多数场景下能成功播放。
增强体验:添加加载状态与防抖优化
为避免快速滚动时反复触发 play/pause,可加简单状态锁:
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
const video = entry.target;
if (entry.isIntersecting && !video.dataset.playing) {
video.play().then(() => {
video.dataset.playing = 'true';
}).catch(() => {
video.dataset.playing = 'false';
});
} else if (!entry.isIntersecting && video.dataset.playing === 'true') {
video.pause();
video.dataset.playing = 'false';
}
});
}, { threshold: 0.1 });
也可结合 video.readyState 判断是否已就绪,或监听 canplay 事件再执行播放逻辑,提升稳定性。
兼容性与降级建议
IntersectionObserver 在主流浏览器中支持良好(Chrome 51+、Firefox 55+、Safari 12.1+)。若需支持更老版本,可用 getBoundingClientRect() + scroll 事件模拟,但务必节流(如使用 requestAnimationFrame)。
对不支持 IntersectionObserver 的环境,可包裹检测逻辑:
if ('IntersectionObserver' in window) {
// 使用 Observer
} else {
// 降级方案:监听 scroll + 节流判断位置
}
同时建议为视频添加 poster 图片,并设置 controls 属性的备用方案(如点击播放按钮),保障无 JS 或策略拦截时的基础可用性。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










