You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:实现视频进入视口后才触发滚动控制播放的功能

滚动控制视频播放优化:仅在视频进入视口后启动播放

我搭建了一个包含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);

关键说明

  1. 视口判断函数:isInViewport通过元素的getBoundingClientRect()方法获取位置,对比视口高度判断元素是否可见。
  2. 相对滚动计算:使用window.pageYOffset - blockOffsetTop获取相对于第3个区块顶部的滚动距离,确保视频从区块进入视口时才开始播放,而非页面一开始滚动就启动。
  3. 状态控制:区块在视口内时自动播放,离开时暂停并重置视频,避免不必要的资源占用。

内容的提问来源于stack exchange,提问作者Pixelharvester

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 21:47:07