使用getBoundingClientRect()检测iframe视口时触发函数不存在错误
问题分析与解决方案
核心错误
你触发getBoundingClientRect() is not a function的原因很直接:你在自己定义的players[i]对象上调用了这个方法,但这个对象不是DOM元素。players数组里的每一项是你手动创建的包含player、top、status的自定义对象,而getBoundingClientRect()是DOM元素的专属方法,自定义对象自然没有这个方法。
修复步骤
1. 保存iframe DOM元素引用
在构建players数组时,把对应的iframe元素也存进去,这样后续就能直接调用getBoundingClientRect():
var players = [] $("iframe").each((index) => { const iframe = $("iframe").get(index); players.push({ player: new Vimeo.Player(iframe), iframe: iframe, // 新增:保存DOM元素引用 status: "paused", }); });
2. 修正视口检测逻辑
在scroll事件里,对保存的iframeDOM元素调用getBoundingClientRect(),同时完善视口交集的判断逻辑(你原来的判断只比较了单一数值,无法准确判断元素是否进入视口):
$(window).on('scroll', function() { for (var i = 0; i < players.length; i++) { const rect = players[i].iframe.getBoundingClientRect(); // 判断元素是否与视口有交集:元素底部大于0,顶部小于视口高度 const isInViewport = rect.bottom > 0 && rect.top < window.innerHeight; const status = isInViewport ? "play" : "pause"; if (players[i].status !== status) { players[i].status = status; players[i].player[status](); console.log(i, status); } } });
更优方案:使用IntersectionObserver
scroll事件会频繁触发,性能较差。推荐使用IntersectionObserverAPI,它专门用于监听元素是否进入视口,性能更优:
var players = [] $("iframe").each((index) => { const iframe = $("iframe").get(index); const player = new Vimeo.Player(iframe); players.push({ player, iframe, status: "paused" }); // 创建观察者:元素10%进入视口时触发 const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { const status = entry.isIntersecting ? "play" : "pause"; const targetPlayer = players.find(p => p.iframe === entry.target); if (targetPlayer && targetPlayer.status !== status) { targetPlayer.status = status; targetPlayer.player[status](); console.log(index, status); } }); }, { threshold: 0.1 }); observer.observe(iframe); });
额外注意点
- 你的HTML里存在多余的闭合标签
</div>和空的<img>标签,建议清理,避免潜在布局问题 - Vimeo播放器的
play()和pause()方法是异步的,若需要等待执行结果,可结合await处理,当前写法无需等待时可正常使用
内容的提问来源于stack exchange,提问作者Robert Carmichael
相关产品推荐
相关产品推荐

