简体   繁体   中英

Make repeated scrollBy smoother like jQuery's animate scrollTop

How can I make a repeated scrollBy call smoother like when animating with jQuery's animate scrollTop?

Currently it is jumpy, the page jumps to and from the different scroll positions. How can I make it smoother?

Here is the scrollBy code:

window.scrollBy(0, -10*(scrollCount ? scrollCount<0 ? -1 : 1 : 0)) , 600*x); })(i);

And here is the for loop that contains it:

for(var i = 0; i < Math.abs(scrollCount); i++){
    (function(x){
        setTimeout(
        window.scrollBy(0, -10*(scrollCount ? scrollCount<0 ? -1 : 1 : 0))
       , 600*x); })(i);
    }
}

try to use animate like this

$('html,body').animate({scrollTop: currentoffset},400);

Usage

First add this to your page.

scrollByAnimated = function(scrollY, duration){
  var startTime = new Date().getTime();

  var startY = window.scrollY;
  var endY = startY + scrollY;
  var currentY = startY;
  var directionY = scrollY > 0 ? 'down' : 'up';

  var animationComplete;
  var count = 0;

  var animationId;

  if(duration === undefined){
    duration = 250;//ms
  }

  //grab scroll events from the browser
  var mousewheelevt=(/Firefox/i.test(navigator.userAgent))? "DOMMouseScroll" : "mousewheel" //FF doesn't recognize mousewheel as of FF3.x

  //stop the current animation if its still going on an input from the user
  var cancelAnimation = function () {
    if(animationId!==undefined){
      window.cancelAnimationFrame(animationId)
      animationId=undefined;
    }

  }

  if (document.attachEvent) {
    //if IE (and Opera depending on user setting)
    document.attachEvent("on"+mousewheelevt, cancelAnimation)
  } else if (document.addEventListener) {
    //WC3 browsers
    document.addEventListener(mousewheelevt, cancelAnimation, false)
  }

  var step = function (a,b,c) {
    var now = new Date().getTime();
    var completeness = (now - startTime) / duration;
    window.scrollTo(0, Math.round(startY + completeness * scrollY));
    currentY = window.scrollY;
    if(directionY === 'up') {
      if (currentY === 0){
        animationComplete = true;
      }else{
        animationComplete = currentY<=endY;
      }
    } 
    if(directionY === 'down') {
      /*limitY is cross browser, we want the largest of these values*/ 
      var limitY = Math.max( document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight );
      if(currentY + window.innerHeight === limitY){
        animationComplete = true;
      }else{
        animationComplete = currentY>=endY;
      }
    } 

    if(animationComplete===true){
      /*Stop animation*/
      return;
    }else{
      /*repeat animation*/
      if(count > 500){
        return;
      }else{
        count++;
        animationId = window.requestAnimationFrame(step);
      }

    }
  };
  /*start animation*/  
  step();
};

Then use it;

scrollByAnimated(100, 250);// change in scroll Y, duration in ms

Explanation

Here's a more robust version than your original code suggested you needed. Additional features include stop scrolling at the top and bottom of the page, uses requestAnimationFrame() .

It also only supports scrolling up and down because thats all I need at this time. You'd be a cool, cool person if you added left and right to it.

It has only been tested in Chrome, so your milage may vary.

This code leverages requestAnimationFrame() . First scrollByAnimated() sets variables, then runs step() which loops until the duration has been reached.

At each frame it calculates the animation's completeness as a number from 0 to 1. This is the difference between the startTime and now , divided by duration .

This completeness value is then multiplied by the requested scrollY . This gives us our amount to scroll for each frame. Then we add the startY position to achieve a value that we can use window.scrollTo() to set the frame's position, rather than increment the current position.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM