求助:实现视频进入视口后才触发滚动控制播放的功能
滚动控制视频播放优化:仅在视频进入视口后启动播放
我搭建了一个包含4个区块的页面,视频绑定在第3个区块上,通过上下滚动控制播放,且视频相对于该区块为sticky定位。当前问题:视频在滚动到第1个区块时就启动了,但我需要它仅在进入视口(viewport)后才开始播放。本人JavaScript能力薄弱,求助实现该功能,以下是现有代码:
现有代码
HTML
<div class="divit" style="height:200vh; background-color: bisque;"> <h1>Block 01</H1> </div> <div class="divit" style="height:200vh; background-color: rgb(95, 120, 145);"> <h1>Block 02</H1> </div> <div class="divit" style="height:1600vh; background-color: rgb(0, 0, 0);"> <h1 class="overlay1">Block 03</h1> <video id="v0" tabindex="0" autobuffer preload> <source type='video/mp4; codecs="avc1.4D401E, mp4a.40.2"' src="scroll_sync_video_a.mp4"></source> </video> </div> <div class="divit" style="height:100vh; background-color: rgb(255, 255, 255);"> <h1>Block 04</h1> </div>
CSS
body { padding:0px; margin:0px; font-family: 'Arial'; } #v0 { display: inline-block; position: sticky; position: -webkit-sticky; top:0px; width: 70%; } .divit { text-align: center; display: block; z-index: 1; position: relative; width: 100%; } h1 { margin: 0px auto; padding: 10%; font-size: 16em; background: #80dbff80; display: inline-block; } .overlay1 { z-index: 10; position: absolute; margin: 0 auto; padding: 10%; font-size: 16em; color:azure; background: #ffffff0c; display: inline-block; }
JavaScript
// start video at frame 0 var frameNumber = 0, // lower numbers = faster playback playbackConst = 1000, // select video element vid = document.getElementById('v0'); // Use requestAnimationFrame for smooth playback function scrollPlay(){ var frameNumber = window.pageYOffset/playbackConst; vid.currentTime = frameNumber; window.requestAnimationFrame(scrollPlay); } window.requestAnimationFrame(scrollPlay);
解决方案
核心逻辑:先获取视频所在的第3个区块元素,编写函数判断该元素是否进入视口;仅当区块处于视口内时,才同步滚动位置与视频播放进度;当区块离开视口时,暂停视频并重置到初始帧。
替换原JavaScript代码为以下版本:
// 初始化变量 var frameNumber = 0, playbackConst = 1000, // 数值越小播放速度越快 vid = document.getElementById('v0'), // 获取视频所在的第3个区块 videoBlock = document.querySelectorAll('.divit')[2]; // 判断元素是否进入视口的函数 function isInViewport(element) { var rect = element.getBoundingClientRect(); return ( rect.top <= window.innerHeight && rect.bottom >= 0 ); } // 滚动同步播放逻辑 function scrollPlay(){ if (isInViewport(videoBlock)) { // 计算当前滚动对应的视频播放进度(仅从区块进入视口的位置开始计算) var blockOffsetTop = videoBlock.offsetTop; var scrollRelativeToBlock = window.pageYOffset - blockOffsetTop; // 确保进度不小于0 var frameNumber = Math.max(0, scrollRelativeToBlock / playbackConst); vid.currentTime = frameNumber; // 如果视频暂停则播放 if (vid.paused) { vid.play(); } } else { // 区块离开视口时暂停视频并重置到初始帧 if (!vid.paused) { vid.pause(); vid.currentTime = 0; } } window.requestAnimationFrame(scrollPlay); } window.requestAnimationFrame(scrollPlay);
关键说明
- 视口判断函数:
isInViewport通过元素的getBoundingClientRect()方法获取位置,对比视口高度判断元素是否可见。 - 相对滚动计算:使用
window.pageYOffset - blockOffsetTop获取相对于第3个区块顶部的滚动距离,确保视频从区块进入视口时才开始播放,而非页面一开始滚动就启动。 - 状态控制:区块在视口内时自动播放,离开时暂停并重置视频,避免不必要的资源占用。
内容的提问来源于stack exchange,提问作者Pixelharvester
相关产品推荐
相关产品推荐

