4

I've made a simple grabbing demo page. It doesn't have any easing/acceleration. I would like to do the same easing/acceleration as on kulesh.info (Flash website) using JavaScript. How can I do that?

Any examples of smooth grabbing (scrolling, dragging) in JavaScript would be helpful as well as a language agnostic algorithm.

NVI
  • 14,907
  • 16
  • 65
  • 104

4 Answers4

8

I think this is the best you can get with jQuery: [Demo]

jQuery.fx.interval = 1; // since v1.4.3
var photos = $(".photos");
var scrollLeft = photos[0].scrollLeft;
var $el = $(photos[0]);
var lastTime = +new Date();


$(window).mousemove(function(event){
    var now = +new Date();
    var elapsed = now - lastTime;
    if (dragging && elapsed > 10) {
        scrollLeft += x - event.clientX;
        $el.stop().animate({scrollLeft:  scrollLeft}, 300, "easeOutCubic");
        x = event.clientX;
        lastTime = +new Date();
    }
});

$(window).mouseup(function(event){
    dragging = false;
    $el.stop().animate({scrollLeft:  scrollLeft}, 500, "easeOutCubic");
});

Note, all the possible (slight) sluggishness can't be corrected at the moment, because it's related to image rendering performance of modern browsers. Test - simple linear animation, no events, no jQuery

gblazex
  • 49,155
  • 12
  • 98
  • 91
3

You can get the flash look by using an easing equation sometimes referred to as zeno's paradox.

position += (destination - position) / damping

I modified your jsFiddle to make use of it: Have a look

If you'd like me to give a more detailed description of zeno's paradox, let me know and I'll post one here with an image or two.

Zevan
  • 10,097
  • 3
  • 31
  • 48
  • Interesting approach, but non-WebKit browsers have noticeable lag when grabbing starts. Doesn't work in Firefox, because you haven't specified second argument. – NVI Nov 30 '10 at 21:21
  • interesting ... haven't specified a second argument for what? – Zevan Dec 01 '10 at 05:44
  • ah i see... second argument of the setInterval function. I've updated my link to include that - was just a simple typo ... I normally include that argument. – Zevan Dec 01 '10 at 08:31
  • which non-Webkit browser or browsers did you test it in? – Zevan Dec 01 '10 at 08:32
  • Firefox 3.6, Opera 10.63, IE8. – NVI Dec 01 '10 at 18:09
  • @st3 - It adds easing but I wouldn't say it's faster: http://jsbin.com/ageci3/14/ – gblazex Jan 12 '11 at 00:45
1

Try replacing this line:

photos[0].scrollLeft += x - event.clientX;

with this (Updated demo):

photos.animate({ scrollLeft : '+=' + (x - event.clientX) }, 12, 'easeOutCirc');

Note that I clicked on jQuery UI to include the easing options. Also, it is very jumpy in the jFiddle (using Firefox) demo, but it doesn't do that at all when I test it on my desktop or if I look at that demo in Chrome. Ideally using the easing function without using jQuery animate would be best. But this should give you an idea.

Mottie
  • 84,355
  • 30
  • 126
  • 241
  • 12ms delay is too small to do any significant change. I almost don't see any difference in Safari, Chrome, and Firefox 4 beta. I've tried to use throttling http://jsfiddle.net/NV/Nkf9n/3/, but it's still much worse comparing to the Flash version. – NVI Nov 21 '10 at 06:46
  • 1
    Well, I messed around with the animation timing and anything greater than 20ms was too much and less than 10ms was too little. It's all really dependent on the browser... I can't think of anything else to do =(... but you might want to consider adding mouse wheel scrolling - I made this demo a while back as an example: http://jsfiddle.net/MvRdD/1/ – Mottie Nov 22 '10 at 17:04
0
var dragging = false;
var x, startX, startTime, stopTime;
var photos = $(".photos");

photos.mousedown(function(event){
    dragging = true;
    startX = x = event.clientX;
    startTime = new Date();
    event.preventDefault();
});

$(window).mousemove(function(event){
    if (dragging) {
        photos[0].scrollLeft += x - event.clientX;
        stopTime = new Date();
        x = event.clientX;
    }
});

$(window).mouseup(function(event){
    dragging = false;
    var left = photos[0].scrollLeft;
    var dx = (startX - event.clientX);
    var time = stopTime - startTime;
    var speed =time/dx;
    photos.animate({ scrollLeft : (left + dx*time/500), easing :'swing' }, 100/time*1000);  
});
  • It adds animation on mouse up, but doesn't change an acceleration while I'm grabbing an image. – NVI Nov 25 '10 at 20:04