Search code examples
javascripthtmlcssscrollhtml5-video

Scroll-based Video start on enter viewport


I set up a page with 4 blocks, a video is controlled by scrolling up/down on block 3. The video is sticky to block 3. Problem: the video should only start when entering the veiwport, not on scroll position block 1.

My Java Script knowledge is very poor, so I ask here for help to write/implement such a function. Here is what I have tinkered so far:

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=&quot;avc1.4D401E, mp4a.40.2&quot;' 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;
        }

JS

        // 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);
    

Here is the HTML test-page: http://scroll.bfg.lu/

Code reference: https://github.com/designcourse/html5-video-scroll/blob/master/index.html


Solution

  • You could get the topOffset of the block 3 and calculate the frame as:

    const block3 = document.querySelector("#block3");
    const frameNumber  = Math.max(0,window.pageYOffset - block3.offsetTop)/playbackConst;
    

    For this to work you need to add the id "block3" to your block3 div