playinThrouLife playinThrouLife - 3 months ago 8
jQuery Question

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>




Answer

After studying your code for a whole bunch of time I figured it out.

The most interesting part is that what makes your problem so damn difficult to solve is yourself. I had to spend almost half a hour to actually get my head into your code. Nothing is sufficiently clear to someone who isn't familiar with it. What does scrolling() is supposed to do? The only thing the name of this function tells me is that it's called when the user is scrolling.


Anyway, turns out that the problem in your code was that you were assigning false to the isScrolling variable too early, actually right after animate() is called, so scrollTop changes triggered the scroll event listener and then if(scrollTop == false) returned true, running the code over and over again. I've solved the problem by waiting for the animate callback to assign false to the respective variable.

Here's a better explanation:

    window.requestAnimationFrame(function() {
      scrolling(e);
      isScrolling = false;
      //console.log("Scrolling");
    });

When your code runs, the computer doesn't wait for scrolling(e); to be completed before going on, mainly because the animate() function you call inside it will run somewhat parallel to the code that's right after this scrolling call, so isScrolling gets immediately assigned to false, causing the next if to pass, which in turn calls this same code again, and again, and again.


Your code isn't bad, you're doing it fine and definitely on the right track. Just try to write things like you were going to have alzheimer or amnesia, and when you come back to your code 10 years from now you'll need to understand every single thing you just typed in there because there's where the cure is.

Every single variable or function name must describe what they do, not when they should be called. scrolling() isn't meaningful, but jumpToNextPage() might be. heightVal isn't meaningful, but windowHeight is. Readability is the most important thing here, and if you think the only way to make a function name crystal clear is to name it makeMyGrandMotherStopComplainingAboutHerLifeAllTheTimeSoICanSleep() then call it like so.

$(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 = true;
        }
    }
    function setScrollingToFalse () {
        isScrolling = false;
    }

    document.addEventListener("DOMContentLoaded", scrolling, false);

    var section1 = document.querySelector("#section1");
    var section2 = document.querySelector("#section2");
    var section3 = document.querySelector("#section3");	

    function scrolling(e) {
        var yValue = $(window).scrollTop();

    //1st photo goin down
    if ( yValue > 0 && scrollCheck === 0 ){
        console.log("how many times this runs?")

        $('body').stop().animate({scrollTop: heightVal}, 700, 'linear', setScrollingToFalse);

        if ( window.pageYOffset === heightVal ){
            scrollCheck = 1;
        //console.log(window.pageYOffset);
        }

    }
    else if( yValue < heightVal  && scrollCheck === 1  ){

        $('body').stop().animate({scrollTop:(0)}, 700, 'linear', setScrollingToFalse);

        if ( window.pageYOffset === 0 ){
            scrollCheck = 0;
        }

    }
    else if( yValue > heightVal  && scrollCheck === 1 ){

        $('body').stop().animate({scrollTop:(heightVal*2)}, 700, 'linear', setScrollingToFalse);

        if ( window.pageYOffset === (heightVal*2) ){
            scrollCheck = 2;
        }

    }
    else if( yValue < heightVal*2 && scrollCheck === 2){
        $('body').stop().animate({scrollTop:(heightVal)}, 700, 'linear', setScrollingToFalse);

        if ( window.pageYOffset === heightVal ){
            scrollCheck = 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>