سؤال

I'm trying to load a video and then play that video based on the scrolling of the window. What I have currently works in Safari and Firefox but not Chrome. The error I keep getting in Chrome is: Uncaught InvalidStateError: Failed to set the 'currentTime' property on 'HTMLMediaElement': The element's readyState is HAVE_NOTHING.

Does anyone know what I'm doing wrong?

function updateVideo(video) {

    var video = $('#trees').get(0);

    var videoLength = video.duration;
    var scrollPosition = $(document).scrollTop();

    video.currentTime = (scrollPosition / ($(document).height() - $(window).height())) * videoLength;//(scrollPosition / SCROLL_SCRUB_SPEED) % videoLength;
    }

    $(window).scroll(function(e) {
        updateVideo();
    });

<video id="trees"><source src="/theme/pmc/files/video/trees_all.mov" type="video/quicktime"><source src="/theme/pmc/files/video/trees_all.webm" type="video/webm"></video>
هل كانت مفيدة؟

المحلول

That error is thrown any time you try to set the currentTime before the browser knows the duration of the video. The duration is part of the "metadata", which is typically in the header of the video file and includes the height and width.

Usually, if you have a video element without a preload attribute, the browser will try to at least load the metadata soon after you load the page. But, depending on the specifics of the browser, the rest of the content on the page and the speed of the network connection, it may not happen until after you've scrolled at least once.

A solution looks something like this.

/*
memoize video, window and document so you don't have to create and
garbage-collect new objects every time you scroll
*/
var video = $('#trees').get(0),
    $window = $(window),
    $document = $(document);

function updateVideo() {
    var duration = video.duration,
       scrollPosition = window.scrollY;
    if (duration) {
        video.currentTime = (scrollPosition / ($document.height() - $window.height())) * duration;
    }
}

// update video every time you scroll
$window.scroll(updateVideo);

// update video when metadata has loaded
$(video).on('loadedmetadata', updateVideo);

That should make the error go away. If you try this and the loadedmetadata event never fires, try adding this to the end to force it:

video.load();

Edit: Defined and set scrollPosition. Here is a working example: http://jsbin.com/vurap/1/edit

نصائح أخرى

Just found a codepen that is a bit faster and does almost the same with less code: http://codepen.io/ollieRogers/pen/lfeLc/

// select video element
var vid = document.getElementById('v0');
//var vid = $('#v0')[0]; // jquery option

// pause video on load
vid.pause();

// pause video on document scroll (stops autoplay once scroll started)
window.onscroll = function(){
    vid.pause();
};

// refresh video frames on interval for smoother playback
setInterval(function(){
    vid.currentTime = window.pageYOffset/400;
}, 40);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top