Difference between current position and scrolled p

2019-07-05 22:14发布

问题:

I'm trying to get difference between current distance of element from the top and its next position after scrolling. In fact I'm trying to choose animation duration depending on its distance. I wrote the code below but it's not work correctly-

I have 6 menu items, which when I clicked on each one, the window scrolled to its position. But the matter is when I click on the last one item it should move over 3000px in 2 second that I want to increase the time by getting the distance. Unfortunately when I add the if - else if section some of items don't work. I meant after clicking on them nothing happened.

var w = window.innerWidth
 || document.documentElement.clientWidth
 || document.body.clientWidth;

 var h = window.innerHeight
 || document.documentElement.clientHeight
 || document.body.clientHeight;


var scrolingMenuTime=1500;
var hashTagActive = "";
    $(".item, .item-f").click(function (ev) {
        if(hashTagActive != this.hash) {
            ev.preventDefault();
            var next = 0;
            if ($(this.hash).offset().top > $(document).height() - $(window).height()) {
                next = $(document).height() - $(window).height();
            } else {
                next = $(this.hash).offset().top;
            }
            var currentPosition=$(this).offset().top;
            var diffPos=Math.abs(next-currentPosition);

        if (diffPos >= h && diffPos < 2*h){
            scrolingMenuTime=1700;
        }else if(diffPos >= 2*h && diffPos < 3*h){
            scrolingMenuTime=2500;
        }else if(diffPost >= 3*h && diffPos < 4*h){
            scrolingMenuTime=3500;
        }else if(diffPos >= 4*h && diffPos < 5*h){
            scrolingMenuTime=4500;
        }else if(diffPos >= 5*h){
            scrolingMenuTime=5500;}
        else{
                return false;
            }
        $('html,body').animate({
            scrollTop: next
        }, scrolingMenuTime, 'easeOutBack');
        hashTagActive = this.hash;
        location.hash = '';
    }
});

And also I have to tell that when I delete the if - else if section then the code works correctly. What is the wrong with if - else if section?

回答1:

You basically need to have some kind of a factor to multiply its value by some certain vertical value, i.e: having 6 links with around 3000px document height means you need to make it so that the more distance between current position and target position is, the more this factor will be to have longer animation period for far distance.

Like in this JS Fiddle

My solution was if you're on "Section TWO" with the link dot (2) activated, if you click on (3) targeting "Section THREE", the animation duration will be Math.abs(2 - 3) * 250 so the scrolling will last for 250ms.

While if you're on "Section TWO" (2) and clicked on link (5) to scroll the page to "Section FIVE", the formula will be Math.abs(2 - 5) * 250 which results a 750ms animation duration.

This solution automated and much less code, unlike if-else if statements which you need to add new condition for every new section. even if your sections varies a lot in height you can get each section height with javascript and compose your own similar formula.

JS:

// initializing 
var prevLinkId = 0,
    body = $('html, body');

/* some code */

// get the numeric part of the linkId of the anchor that just been clicked
// remove the active .highlight class name from all links
// and assign it to the just clicked link
linkId = $(this).attr('id');
linkId = linkId.replace('lnk', '');
links.removeClass('highlight');
$(links[linkId]).addClass('highlight');

// compute the absolute differet between the previous link value and the new one
// to have a variable factor when multiplied by the step "here 250ms" we get
// longer durations for larger distances, then we perform the scrolling
// below is the part responsible for making flexible durations
diff = Math.abs(linkId - prevLinkId);
timeDelay = diff * 250;
distance = index * secHeight;
body.animate({scrollTop: distance} , timeDelay);

//finally set the just clicked link as previous link for future calculations
prevLinkId = linkId;