最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How can I make a custom progress bar for a YouTube embed animate smoothly? - Stack Overflow

programmeradmin1浏览0评论

Theres something about a progressing YouTube video that makes it difficult to produce a smoothly animating progress bar. Even YouTube's built in progress bar isnt smooth. Yet I think there must be a way to do it.

I'm using custom controls for a YouTube embed and my progress bar is moving along in a jumpy manner rather than smoothly. Here's the code:

vidClock = setInterval(function() {
    if (state == 1) {
        var time = player.getCurrentTime();
        var percent = (time / duration) * 100;
        $seekSlider.css({
            'width' : percent + '%'
        });
    }
}, 100);

This variable origins aren't all shown but what they represent should be apparent. How can I make the bar move smoothly?

I tried adding a CSS transition effect to the element and also tried setting smaller intervals such as 10,20, and 30 (and after suggestion, have tried using JQuery animate).

Example, using $.animate as suggested by an answer below is not smooth: /

Theres something about a progressing YouTube video that makes it difficult to produce a smoothly animating progress bar. Even YouTube's built in progress bar isnt smooth. Yet I think there must be a way to do it.

I'm using custom controls for a YouTube embed and my progress bar is moving along in a jumpy manner rather than smoothly. Here's the code:

vidClock = setInterval(function() {
    if (state == 1) {
        var time = player.getCurrentTime();
        var percent = (time / duration) * 100;
        $seekSlider.css({
            'width' : percent + '%'
        });
    }
}, 100);

This variable origins aren't all shown but what they represent should be apparent. How can I make the bar move smoothly?

I tried adding a CSS transition effect to the element and also tried setting smaller intervals such as 10,20, and 30 (and after suggestion, have tried using JQuery animate).

Example, using $.animate as suggested by an answer below is not smooth: http://jsfiddle/e11oy0eu/290/

Share Improve this question edited Jun 9, 2016 at 0:29 asked Jun 2, 2016 at 3:52 user5536767user5536767 1
  • 1 There must be some way to get a smooth progress bar animation. I notice even youtube's progress bar isnt smooth, but it seems like there must be a way to do it. – user5536767 Commented Jun 6, 2016 at 19:12
Add a ment  | 

4 Answers 4

Reset to default 2

You can use the .animate() function:

vidClock = setInterval(function() {
    if (state == 1) {
        var time = player.getCurrentTime();
        var percent = (time / duration) * 100;
        $seekSlider.animate({
            'width' : percent + '%'
        },500);
    }
}, 500);

Or use CSS animations:

CSS:

.progress {
    width: 0%;
    height: 100%;
    background-color: green;
    transition: all 0.5s linear;
}

JS:

vidClock = setInterval(function() {
    if (state == 1) {
        var time = player.getCurrentTime();
        var percent = (time / duration) * 100;
        $seekSlider.css({
            'width' : percent + '%'
        });
    }
}, 500);

I chose a different approach for fixing your problem, first of all I added Velocity.js to the project because as Alon said in his answer, it gives you a little better animations, then instead of setting a timer and changing the progress bar size based on the current time of the player, I created a progress bar that always animates to 100%, then used some events to stop the progress bar when the video play stops(by user or when it stops for buffering). While this strategy has its downsides, it gives you smoother animation.

Also for an even smoother animation, instead of changing the div width, I changed the .progress div's position to absolute and moved it using the transform:translateX property.(I am not sure that how much effective was this change, maybe it was not effective at all).

.progress-container {
  width: 640px;
  height: 30px;
  background-color: #efefef;
  position: relative;
  overflow: hidden;
}

.progress {
  width: 100%;
  height: 100%;
  background-color: green;
  position: absolute;
  left: -100%;
  top: 0;
}

After these changes, the handleState function looks like this:

function handleState(state) {
  var $seekSlider = $('.progress');
  var $seekContainer = $('.progress-container');

  if (state == 1) { // when player starts playing
    duration = player.getDuration();
    currentTime = player.getCurrentTime();
    currentLocation = ((currentTime/duration) * 100).toFixed(4);

    $seekSlider
      .velocity('stop')
      .velocity({
        'translateX': currentLocation + '%'
      }, {duration: 0})
      .velocity({
        'translateX': '100%'
      }, {
        duration: Math.floor((duration-currentTime) * 1000),
        easing: 'linear'
      });
  }

  if (state == 2 || state == 3 || state == 0) {
    $seekSlider.velocity('stop');

    if (state == 3) {
      duration = player.getDuration();
      currentTime = player.getCurrentTime();
      currentLocation = ((currentTime/duration) * 100).toFixed(4);

      $seekSlider.velocity({
        'translateX': currentLocation + '%'
      }, {duration: 0});
    }

    if (state == 0) {
        $seekSlider.velocity({
        'translateX': '100%'
      }, {duration: 0});
    }
  }
}

You can see the working result and plete code with some ments in this JSFiddle, Also I have created a gist that shows the differences between your script and my script.

The chunky progressing is not only caused by the getCurrentTime function, but also by the way you are resizing the progress bar. Even though you are setting the CSS width in percent, it will always render as whole pixels. You can use transform instead, which will render "half" pixels as well.

Next, to overe the limitation of getCurrentTime not updating on each call, you can save its value in a variable and increase it manually with the timer interval:

function handleState(state) {
  var $seekSlider = $('.progress');
  var $seekContainer = $('.progress-container');
  if (state == 1) {
    duration = player.getDuration();
    var prevTime = 0;
    var elapsed = 0;
    vidClock = setInterval(function() {
      elapsed += 0.05; // Increase with timer interval
      if ((state == 1) && (seeking == false)) {
        var time = player.getCurrentTime();
        if (time != prevTime) {
          elapsed = time; // Update if getCurrentTime was changed
          prevTime = time;
        }
        var percent = (elapsed / duration);
        $seekSlider.css({
          'transform': 'scaleX(' + percent + ')'
        });
      }
    }, 50);
  } else {
    clearInterval(vidClock);
  }
}

See updated fiddle

You can use Velocity.js. Its animation is a lot smoother than jQuery and the configuration is as simple as the jQuery one.

look at this parison: http://webdesign.tutsplus./tutorials/silky-smooth-web-animation-with-velocityjs--cms-24266

发布评论

评论列表(0)

  1. 暂无评论