Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery scrollTo but slow down inbetween

I'm using a simple chunk of code (based of 'ScrollTo Posts with jQuery' which allows you to click a next/previous link and it'll jump through to the top of each post.

I have my HTML structure so it goes post > image > post > image etc.

I'm wondering if it's possible that if you click the next/previous button, it scrolls to the next post as normal, but it hangs/hovers over the images/div inbetween? So it eventually completes it's scroll, but slows down over the divs inbetween.

Here's my jQuery code:

$(function () {
    function a(f) {
        var b, e, c = [],
            d = $(window).scrollTop(),
            g = $('.section-slide');
        g.each(function () {
            c.push(parseInt($(this).offset()['top'], 10))
        });
        for (e = 0; e < c.length; e++) {
            if (f == 'next' && c[e] > d) {
                b = g.get(e);
                break
            }
            if (f == 'prev' && e > 0 && c[e] >= d) {
                b = g.get(e - 1);
                break
            }
        }
        if (b) {
            $.scrollTo(b, {
                duration: 1400
            })
        }
        return false
    }
    $('#next,#prev').click(function () {
        return a($(this).attr('id'))
    });
    $('.scrolltoanchor').click(function () {
        $.scrollTo($($(this).attr('href')), {
            duration: 1400
        });
        return false
    })
});
like image 897
John the Painter Avatar asked Feb 20 '13 11:02

John the Painter


2 Answers

Assuming your structure will remain static: post -> image -> post -> image etc. you can accomplish this by finding the previous / next image to the post you will be scrolling to, and scrolling to it first, then use the onAfter callback/setting from the $.scrollTo plugin to fire a secondary scroll after a predefined setTimeout like this:

$(function () {
    function scroll(direction) {
        var scroll, scrollImage, i,
            positions = [],
            here = $(window).scrollTop(),
            collection = $('.post');

        collection.each(function () {
            positions.push(parseInt($(this).offset()['top'], 10));
        });

        for (i = 0; i < positions.length; i++) {
            if (direction == 'next' && positions[i] > here) {
                scroll = collection.get(i);

                // Find Image Before Post
                scrollImage = $(scroll).prev('.image').get(0);

                break;
            }
            if (direction == 'prev' && i > 0 && positions[i] >= here) {
                scroll = collection.get(i - 1);

                // Find Image After Post
                scrollImage = $(scroll).next('.image').get(0);

                break;
            }
        }

        if (scroll) {
            // Check if Scroll Image Exists
            if (scrollImage){
                // Scroll with Image Delay
                $.scrollTo(scrollImage, {
                    duration: 750,
                    onAfter: function(){
                        setTimeout(function(){
                            $.scrollTo(scroll, {
                                duration: 750
                            });
                        }, 1000); // Change the Delay to Increase / Decrease the Hover
                    }
                });                
            } else {
                $.scrollTo(scroll, {
                    duration: 750
                });
            }
        }

        return false;
    }

    $("#next,#prev").click(function () {
        return scroll($(this).attr('id'));
    });

    $(".scrolltoanchor").click(function () {
        $.scrollTo($($(this).attr("href")), {
            duration: 750
        });
        return false;
    });
});

You can find an updated fiddle here: http://jsfiddle.net/hfg2v/2/

I hope this helps.

like image 171
dSquared Avatar answered Sep 29 '22 23:09

dSquared


This is happening because you're using a parallax scrolling library (Stellar.js), which makes different elements scroll at different speeds.

A possible fix would be to scroll at a higher speed when no element is in the current viewport until the edge of the next element is just off the screen, then immediately scroll at the original scrolling speed until there are no elements in the viewport again, and keep repeating this until you reach the desired scroll offset.

Edit:

Sorry, something came up while I was writing my answer and I didn't have time to finish the code.

However, after working on it for some time I'm starting to think that my proposed solution wouldn't work. I was thinking something along those lines:

$(window).scrollTo(640, {onAfter: function () {
    var scrollRatio = 3;
    var distance = 855 - 640;

    $(window).scrollTo(855, {
        easing: 'linear',
        duration: distance * scrollRatio / speed,
        onAfter: function () {
            var scrollRatio = 1;
            var distance = 1200 - 855;
            $(window).scrollTo(1200, {
                easing: 'linear',
                duration: distance * scrollRatio / speed,
                onAfter: function () {
                    var scrollRatio = 3;
                    var distance = 1280 - 1200;
                    $(window).scrollTo(1280, {
                        easing: 'linear',
                        duration: distance * scrollRatio / speed
                    });
                }
            });
        }
    });
}});

If you paste the previous code in the website provided in the question (http://dev.du.st/field-station/), you'll be taken to the first element, and it will attempt to scroll you to the next one using the method I described. I hardcoded the offset values because I was still experimenting with it. However, I don't think this approach would work since it still feels off. This is because changing instantly speed in the middle of the animation will always be noticeable.

Right now, I think the best way you can mitigate the slow-scrolling feel that parallax scrolling is causing is by using a different easing function. After all, making the background pictures slower, is exactly what you're using parallax scrolling for.

The following code, when ran in your website, would make all animations use 'easeOutCirc' for their easing function by default, after some experimenting, I found it to be the one that makes the scrolling feel least odd:

// Add the jQuery-easing plugin, needed for the more sophisticated easing functions.
$.getScript('//cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.3/jquery.easing.min.js');

// Set easeOutCirc as the default easing.
jQuery.easing.def = 'easeOutCirc';

You can find more easing functions at this website

Once you're done experimenting, if you do decide on using an easing (you can use different ones for scrolling up and down), then you should probably keep the default easing as is, and just change the easing in the scroll animation by adding {easing: EASING_NAME} to your options hash in the scrollTo function. So your code will look something like this:

$.scrollTo($($(this).attr("href")), {
    duration: 750,
    easing: 'easeOutCirc'
});
like image 27
maljub01 Avatar answered Sep 30 '22 01:09

maljub01