IntersectionObserver与视频play()命令冲突问题排查与解决
视频切换播放与IntersectionObserver冲突问题分析及解决
冲突原因
点击图片切换视频src时,视频元素会触发重新加载流程,这个过程中视频元素的交集状态可能发生短暂变化(比如加载时渲染状态改变,被IntersectionObserver判定为“不在视口内”),导致Observer回调执行pause()方法,直接打断刚发起的play()请求,从而抛出Uncaught (in promise) DOMException: The play() request was interrupted by a call to pause().错误。
解决方法
方法1:切换视频时临时停止观测,播放后恢复
在切换视频的逻辑中,先暂停IntersectionObserver对视频元素的观测,等视频加载完成并成功播放后再恢复观测,避免加载过程中误触发暂停。
修改后的完整JS代码:
var vsingle = $('#vsingle'); const io = new IntersectionObserver((entries) => { entries.forEach(entry => { if(!entry.isIntersecting){ entry.target.pause() } }); }); $(document).ready(function(){ io.observe(document.querySelector('#vsingle')); }); $('.aimg').on('click', function(){ let src = $(this).attr('data-v'); // 临时停止观测 io.unobserve(vsingle[0]); vsingle.attr('src', src); // 监听视频加载完成事件,确保就绪后再播放 vsingle.one('loadeddata', function() { this.play() .then(() => { // 播放成功后恢复观测 io.observe(this); }) .catch(err => { // 处理播放失败(如用户未交互),仍需恢复观测 io.observe(this); }); }); });
方法2:在Observer回调中增加状态判断
通过视频元素的readyState属性判断视频是否已加载完成,仅当视频就绪且不在视口内时才执行暂停操作,避免加载过程中误触发。
修改后的IntersectionObserver代码:
let io = new IntersectionObserver((entries) => { entries.forEach(entry => { // readyState >=2 表示视频已加载到可播放状态 if(!entry.isIntersecting && entry.target.readyState >= 2){ entry.target.pause() } }); }); $(document).ready(function(){ io.observe(document.querySelector('#vsingle')); });
方法3:延迟执行play()并配合观测状态检查
切换src后延迟一小段时间再调用play(),同时检查视频当前是否在视口内,确保不会被Observer的暂停操作打断。
修改后的点击事件代码:
$('.aimg').on('click', function(){ let src = $(this).attr('data-v'); vsingle.attr('src', src); // 延迟执行,给Observer和视频加载留处理时间 setTimeout(() => { // 检查视频是否在视口内,再执行播放 const isIntersecting = io.takeRecords()[0]?.isIntersecting; if(isIntersecting){ vsingle[0].play().catch(err => console.error(err)); } }, 100); });
内容的提问来源于stack exchange,提问作者provance
相关产品推荐
相关产品推荐

