Search code examples
jqueryeasing

Linear easing slows down


1st question: Can't figure out why .animate linear slows down when it comes to its destination point. What am I missing ?

Weird thing is that going from middle pic upward it always works perfectly (only in that one case).

2nd question: Is there a way to disable user from scrolling while animation is on-going ?

[edit] I have cut out pictures so it is easier to debug [/edit]

$(document).ready( function (){
	var scrollCheck = 0;
	var heightVal = window.innerHeight;
			
			
	$(window).resize(function(){
	  window.scroll(0,0);
	  heightVal = window.innerHeight;
	  hControl1 = heightVal -1;
	  scrollCheck = 0;
	});

	var isScrolling = false;
		
	window.addEventListener("scroll", throttleScroll, false);
				 
	function throttleScroll(e) {
	  if (isScrolling == false) {
	    window.requestAnimationFrame(function() {
	      scrolling(e);
	      isScrolling = false;
	      //console.log("Scrolling");
	    });
	  }
	isScrolling = true;
	}
				 
	document.addEventListener("DOMContentLoaded", scrolling, false);
	
	function scrolling(e) {
	var yValue = $(window).scrollTop();
					 
	  //1st photo, scroll down
	  if ( yValue > 0 && scrollCheck === 0 ){
					 	
	    $('body').stop().animate({scrollTop:heightVal}, 700, 'linear');
	    if ( window.pageYOffset === heightVal ){
	      scrollCheck = 1;
	      //console.log(window.pageYOffset);
	    }
	  }//2nd photo, scroll up
	  else if( yValue < heightVal  && scrollCheck === 1  ){
					 	
	    $('body').stop().animate({scrollTop:(-heightVal)}, 700, 'linear');
	    if ( window.pageYOffset === 0 ){
	      scrollCheck = 0;
	    }
	  }//2nd photo, scroll down
	  else if( yValue > heightVal  && scrollCheck === 1 ){

	    $('body').stop().animate({scrollTop:(heightVal*2)}, 700, 'linear');
            if ( window.pageYOffset === (heightVal*2) ){
	      scrollCheck = 2;
	    }
	  }//3rd photo, scroll up
	  else if( yValue < heightVal*2 && scrollCheck === 2){

            $('body').stop().animate({scrollTop:(heightVal)}, 700, 'linear');
		if ( window.pageYOffset === heightVal ){
		  scrollCheck = 1;
		}
	  }
    }//end of scrolling(e) funcion
}); //end of $(document).ready
html,body{
  margin: 0;
  height: 100%;
  width: 100%;
}
#section1,#section2,#section3{
  height: 100%;
  width: 100%;
  vertical-align: top;
}
#section1{
  background-color: grey;
}
#section2{
  background-color: green;
}
#section3{
  background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='section1'></div>

<div id='section2'></div>

<div id='section3'></div>


Solution

  • animate() won't run linearly because you're calling it every time the scroll event is triggered. This happens because when you do this:

    $("body").stop().animate({scrollTop: 0}, 700);
    isScrolling = false;
    

    The computer doesn't wait for the animation to complete to continue the program flow; instead, it starts the animation and procceeds, assigning false to the isScrolling variable immediately. In addition, your usage of requestAnimationFrame wasn't necessary, and it led the isScrolling = false assignment to run after isScrolling = true with virtually no delay — due to the asynchronous nature of those functions.

    This causes the scroll event listener to call the animate() function every time it's triggered, because isScrolling is never true.

    The problem can be solved by waiting for the animate() callback to assign false to isScrolling, removing the requestAnimationFrame call and it's isScrolling = false; assignment.


    One last thing...

    Weird thing is that going from middle pic upward it always works perfectly (only in that one case).

    No, it doesn't, but it looks like so because you set it to {scrollTop: -heightVal}, while it should be {scrollTop: 0}.

    Note that I highly, HIGHLY recommend an extensive refactoring of functions and variable names. No one other than you can understand your code in less than 30 minutes.

    Here's the result of all the changes above mentioned, including better naming:

    $(document).ready( function (){
    var currentSection = 0;
    var windowHeight = window.innerHeight;
    
    
    $(window).resize(function(){
        window.scroll(0,0);
        windowHeight = window.innerHeight;
        hControl1 = windowHeight -1;
        currentSection = 0;
    });
    
    var isScrolling = false;
    
    
    window.addEventListener("scroll", scrollSnappingController, false);
    
    function scrollSnappingController(e) {
        if (isScrolling === false) {
                snapScrollToNextSection(e);
                console.log("first")
            isScrolling = true;
            console.log("second")
        }
    }
    function scrollEnded () {
        isScrolling = false;
    }
    
    document.addEventListener("DOMContentLoaded", snapScrollToNextSection, false);
    
    var section1 = $("#section1");
    var section2 = $("#section2");
    var section3 = $("#section3");
    
    function snapScrollToNextSection(e) {
        var scrollPosition = $(window).scrollTop();
    
        //1st photo goin down
        if ( scrollPosition > 0 && currentSection === 0 ){
            $('body').stop().animate({scrollTop: windowHeight}, 700, 'linear', scrollEnded);
    
            if ( scrollPosition === windowHeight ){
                currentSection = 1;
            }
    
        }
        else if( scrollPosition < windowHeight  && currentSection === 1  ){
    
            $('body').stop().animate({scrollTop:(0)}, 700, 'linear', scrollEnded);
    
            if ( scrollPosition === 0 ){
                currentSection = 0;
            }
    
        }
        else if( scrollPosition > windowHeight  && currentSection === 1 ){
    
            $('body').stop().animate({scrollTop:(windowHeight*2)}, 700, 'linear', scrollEnded);
    
            if ( scrollPosition === (windowHeight*2) ){
                currentSection = 2;
            }
    
        }
        else if( scrollPosition < windowHeight*2 && currentSection === 2){
            $('body').stop().animate({scrollTop:(windowHeight)}, 700, 'linear', scrollEnded);
    
            if ( scrollPosition === windowHeight ){
                currentSection = 1;
            }
    	}
    
    
    }
    });
    html,body{
    margin: 0;
    height: 100%;
    width: 100%;
    }
    
    img{
    display: block;
    height:100%; 
    width:100%;
    margin: 0;
    padding:0;
    }
    
    #section1,#section2,#section3{
    height: 100%;
    width: 100%;
    vertical-align: top;
    }
    #section1{
    background-color: grey;
    }
    #section2{
    background-color: green;
    }
    #section3{
    background-color: red;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div id='section1'></div>
    
    <div id='section2'></div>
    
    <div id='section3'></div>