jQuery Animation Speed?

Langdon picture Langdon · Jul 7, 2010 · Viewed 61.6k times · Source

Final Edit: The wall of text below can be summed up by simply asking "can I specify the speed of animations using jQuery's animate()? All that is provided is duration."

~~

jQuery's animate() seems to implement easing despite my use of "linear". How can I get the two boxes to stay together until the first finishes @ 250px? The second animates much faster because it has a longer distance to go.

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script type="text/javascript">
    $(function()
    {
        $('#a').animate({left: '250px'}, 1000, 'linear');
        $('#b').animate({left: '500px'}, 1000, 'linear');
    });
</script>

<div id="a" style="background-color: red; position: relative; width: 50px; height: 50px;"></div>
<br/><br/>
<div id="b" style="background-color: red; position: relative;width: 50px; height: 50px;"></div>

Alternatively is there a jQuery carousel plugin that does this (mouse movement based on where you're mousing) so I don't have to rewrite it? I spent about 20 minutes looking for one on Google but couldn't come up with anything I liked.

ETA: The example I provided is very simple, but the issue as I found it is applied to a more complex code base. (1) Go here. (2) Put mouse on C. Viper, see the speed. (3) Put mouse on Ryu, but before it finishes, move your mouse to the middle of the DIV (so it stops). (4) Put your mouse back on the left side and see how utterly slow it moves.

Calculating the differences in speed and distance seems insurmountable here. All I'm trying to do is recreate a lovely effect I saw a site use today (this site). But it's Mootools, and I'm in jQuery. =[

Answer

Nick Craver picture Nick Craver · Jul 7, 2010

For the updated question:
First, here's a working demo with the behavior you want. What we're doing here is adjusting the speed based on the amount needed to move, because speed isn't an accurate description, it's the duration, moving a shorter distance over the same duration means a slower move, so we need to scale the duration with the distance we need to move. For moving backwards, it looks like this:

var oldLeft = ul.offset().left;
ul.animate({left: 0}, -oldLeft * speed, 'linear');

Since the <ul> scrolls with a negative left position, we need to move the inverse of that many pixels to get back to the beginning, so we're using -oldLeft (it's current left position).

For the forward direction, a very similar approach:

var newLeft = divWidth - ulWidth,
    oldLeft = ul.offset().left;
ul.animate({left: newLeft + 'px'}, (-newLeft + oldLeft) * speed, 'linear');

This gets the new left property, the end being the width of the <ul> minus the width of the <div> it's in. Then we subtract (it's negative so add) that from the current left position (also negative, so reverse it).

This approach gives your speed variable a whole new meaning, it now means "milliseconds per pixel" rather than the duration it did before, which seems to be what you're after. The other optimization is using that cached <ul> selector you already had, making things a bit faster/cleaner overall.


For the original question:
Keep it simple, just half the time for half the distance, like this:

$(function() {
    $('#a').animate({left: '250px'}, 500, 'linear');
    $('#b').animate({left: '500px'}, 1000, 'linear');
});

You can try a demo here