chadpeppers
chadpeppers

Reputation: 2057

jQuery smooth scroll on mousedown

Is there any way to emulate a scroll type option using jquery animate? Right now it simply scrolls equivalent to the value you give it (like below). I cannot do a custom scroll bar on this div because its mainly geared towards making it easy to scroll on mobile devices. So the example below will scroll buy it goes -100px from the top, but then stops, and repeats. Is there any easy way to make this a transition that it will just continue.

jQuery(".down-arrow").mousedown(function(){
        var height = jQuery("#technology_list").height();
        //if($('#technology_list').offset().top 
        scrolling = true;
        startScrolling(jQuery("#technology_list"), "-=100px");
        //jQuery("#technology_list").animate({top: '-=25'});
    }).mouseup(function(){
        scrolling = false;
    });

    function startScrolling(obj, param)
{
    obj.animate({"top": param}, "fast", function(){
        if (scrolling)
        {
                startScrolling(obj, param);
        }
    });

Upvotes: 1

Views: 3608

Answers (3)

Mark Pieszak - Trilon.io
Mark Pieszak - Trilon.io

Reputation: 66961

jsFiddle showing it in action

Simplest answer would be that you want to make sure you set your animate to have easing set to linear.

.animate( { /* whats animating */ } , duration: 'XXX', easing: 'linear'
   ,function () { /* callback */ } 
);

Strangely enough, when easing is left out of animate() its default actually isn't linear (which basically turns it off). The default is a standard easing, which eliminates that "smoothness", one speed through out the entire animation that we'd want here.

Here's an example so you can see it:

var end = 20;

for (i = 0; i < end; i++) {
  $('#test').animate({'top': '+=50px'}, 500, 'linear', function () {
      // callback
  });
}

Upvotes: 4

A.M.K
A.M.K

Reputation: 16795

I had the same problem a little while ago and put this together, basically it is an infinite scroll solution:

EDIT: Here is my code adapted for your use case:

// Assuming you also have/want a scroll up
jQuery(".up-arrow").mousedown(function() {
    // You don't need to use jQuery instead of $ inside of jQuery defined functions 
    var offset = $("#technology_list").offset();
    var topValue = offset.top;
    if ((topValue * 2) < 1000) speed = topValue * 3;
    else if ((topValue * 2) < 500) speed = topValue * 4;
    else if ((topValue * 2) < 100) speed = topValue * 8;
    else speed = topValue * 2;

    $("#technology_list").animate({
        top: 0
    }, speed);

}).mouseup(function() {
    $("#technology_list").stop();
});

jQuery(".down-arrow").mousedown(function() {
    var offset = $("#technology_list").offset();
    var topValue = offset.top;
    var height = $("#technology_list").height();
    if (((height - topValue) * 2) < 1000) speed = (height - topValue) * 2;
    else if (((height - topValue) * 2) < 500) speed = (height - topValue) * 2;
    else if (((height - topValue) * 2) < 100) speed = (height - topValue) * 2;
    else speed = (height - topValue) * 2;

    $("#technology_list").animate(function() {
        top: $("#technology_list").height()
    }, speed);


}).mouseup(function() {
    $("#technology_list").stop();
});​

End of edit.

$(".scroll-left").hover(function() {

    if (($(this).parent().scrollLeft() * 2) < 1000) speed = $(this).parent().scrollLeft() * 3;
    // If it is less than 500 pixels from the edge, then it takes 3 times as long as the scrollLeft value in milliseconds. (Sorry about the if's being hard to read)

    else if (($(this).parent().scrollLeft() * 2) < 500) speed = $(this).parent().scrollLeft() * 4;
    // And if it is less than 250  pixels, it takes 4 times as long

    else if (($(this).parent().scrollLeft() * 2) < 100) speed = $(this).parent().scrollLeft() * 8;
    // Less than 50, it takes 8 times as long

    else speed = $(this).parent().scrollLeft() * 2;
    // And if it is more than 500 run it at 2 milliseconds per pixel

    $(this).parent().animate({
        scrollLeft: 0
    }, speed);
    // Scroll it to the beginning at the above set speed
}, function() {
    $(this).parent().stop();
    // On mouseOut stop the animation
});

$(".scroll-right").hover(function() {
    parent = $(this).parent()[0];
    parentWidth = $(this).parent()[0].scrollWidth;
    // Cache parent and parentWidth (stops delay on hover)

    if (((parentWidth - parent.scrollLeft) * 2) < 1000) speed = (parentWidth - parent.scrollLeft) * 2;
    // Pretty much the same thing as before but this time it sort of makes a "scrollRight"

    else if (((parentWidth - parent.scrollLeft) * 2) < 500) speed = (parentWidth - parent.scrollLeft) * 2;

    else if (((parentWidth - parent.scrollLeft) * 2) < 100) speed = (parentWidth - parent.scrollLeft) * 2;

    else speed = (parentWidth - parent.scrollLeft) * 2;

    $(this).parent().animate({
        scrollLeft: $(this).siblings(".row-scroll").width()
    }, speed);
    // Same thing as before, but this time we scroll all the way to the right side
}, function() {
    $(this).parent().stop();
});​

This is directly copied from my code but the idea is sound, the multiplication slows it down when it is close to the edge.

It isn't perfect or near it and if you want something more fine-tuned then you should try Pause

Upvotes: 2

Abel Mohler
Abel Mohler

Reputation: 794

You could try using the jQuery plugin ScrollTo: http://demos.flesler.com/jquery/scrollTo/

Upvotes: 1

Related Questions