November 11, 2012

Adding easing to the following jQuery animation?

Question by alexchenco

I’m animating the height of element:

  // Animate height of items
  $j(".item .row").toggle(function(){
    $j(this).animate({height:500},200);
  },function(){
    $j(this).animate({height:300},200);
  });

I was wondering how to add easing to it? (e.g. the animation slowing down towards the end?)

Answer by Starx

Define easing, the following way

$('selector').animate({
    prop:1
},{
    easing: easing, //Something like 'linear'
    duration: duration,
    complete: callback
});

You can add other easing effects also, by including the Easing Plugin.

In your case, it would be something like

$j(".item .row").toggle(function(){
    $j(this).animate({height:500}, {
        easing: 'linear',
        duration: '200'
    });
  },function(){
    $j(this).animate({height:300},{
        easing: 'linear',
        duration: '200'
    });
});
October 29, 2012

Animate/Ease an element to position when other elements disappear

Question by Jonathan

Please take a look at this fiddle: http://jsfiddle.net/dhcyA/

Try clicking on a block. What I want is that when the other elements disapear, the selected block will animate/ease to his giving position instead of just jumping like it does now. Then the same animation repeats itself when clicking again on the box, but then back to place.

Maybe to keep in mind:
I’m using a reponsive design, which means those blocks can be vertical and horizontal after scaling the window.

Any redevisions on the fiddle or suggustions would be great!

Answer by Starx

Here is my solution & features it offers:

  • Remembers the last position and gradually animate to/from this position
  • Block positions are calculated and animated on load and every resize
  • Repositioning happens on $(window).resize() thus maintaining the fluid nature of the block, despite the use of position absolute
  • Support variable heights
  • Minor change on existing markup & CSS

On your existing markup, I added a wrapper division.

<div id="wrapper">
    <div class="block">
        <h2>I'm block 1</h2>
    </div>
    ....
</div>

To maintain the fluidness of the block, I created a function to position the block on the wrapper. Here is the function for position of the blocks:

var reposition = function() {
    wrapper = $("#wrapper");
    pLeft = 0; //The starting point of all repositioning
    pTop = 0;

    maxRowHeight = 0;

    $(".block").each(function(){
        $(this).stop(0,0).animate({
          'top' : pTop + 'px',
          'left' : pLeft + 'px'
        });

        pLeft += $(this).width(); //Add the left position for next block

        if($(this).height() > maxRowHeight) maxRowHeight = $(this).height(); //Find out the longest block on the row

        //If the next block will exceed the width of the wrapper
        if(pLeft + $(this).next().width() >= wrapper.innerWidth()) {
           pLeft = 0; //reset the left
           pTop += maxRowHeight;
           maxRowHeight = 0; 
        }
    });    
};

Finally, the script to toggle the block

$(".block").click(function() {

    $(this).siblings().slideToggle('slow'); //Toggle other blocks

    if(!$(this).data('active')){ //if the block is not active
        $(this).data('left', $(this).position().left); //sets its left
        $(this).data('top', $(this).position().top);   // and top position
        $(this).animate({ //animate at the top and bottom
            top:0,
            left:0
        },'slow');

        $(this).data('active',true);

    }else{

        $(this).animate({ //animate to its last known position
            top:$(this).data('top'),
            left:$(this).data('left')
        },'slow');

        $(this).data('active',false);
    }
});

Demos

  • Demo[Full] (Resize this to see the fluidness maintained)
  • Demo[Full] (version supporting variable heights)
June 29, 2012

The animate callback function called immediately

Question by Ajax3.14

I am using the below line to blink a block. It works but the callback function incre() is called immediately and does not wait till blinking is over.

I need to call incre() only after the animate function blinks 2 seconds. What am I missing?

block.attr({ opacity: 0.3 }).animate({ opacity: 1 }, 2000,incre());

Answer by Starx

For what you are attempting fadeTo() sounds like a good choice

block.fadeTo(2000, 0.3, function() {
    block.fadeTo(2000, 1);
});

Demo

However, the error in your codes are:

  • the () (Brackets after the callback function name) i.e. incre()
  • opacity is a CSS property not an attribute. so user .css() to manipulate them

The correct codes are:

block
   .css({ opacity: 0.3 })
   .animate({ opacity: 1 }, 2000, incre);

Working Demo

April 29, 2012

How do I animate in jQuery without stacking callbacks?

Question by yuval

Let’s say I have three divs, and I’d like each to animate once the previous one is done. Currently, I write this:

$('div1').fadeOut('slow', function() {
    $('div2').fadeOut('slow', function() {
        $('div3').fadeOut('slow');
    });
});

Which is ugly, but manageable.

Now imagine I have 10 different animations that need to happen one after the other on different elements. Suddenly the code gets so clunky that it’s extremely hard to manage…

Here’s pseudocode for what I’m looking to do:

$('div1').fadeOut('slow' { delay_next_function_until_done: true } );
$('div2').fadeOut('slow' { delay_next_function_until_done: true } );
$('div3').animate({ top: 500 }, 1000 );

How do I achieve this?

Answer by Julian Aubourg

If you’re using a recent version of jQuery, use the animation promises:

$('div1').fadeOut('slow' ) ).promise().pipe(function() {
    return $('div2').fadeOut('slow' );
}).pipe(function() {
    return $('div3').animate({ top: 500 }, 1000 );
});

You can make it generic:

$.chain = function() {
    var promise = $.Deferred().resolve().promise();
    jQuery.each( arguments, function() {
        promise = promise.pipe( this );
    });
    return promise;
};

var animations = $.chain(function() {
    return $('div1').fadeOut('slow');
}, function() {
    return $('div2').fadeOut('slow');
}, function() {
    return $('div3').animate({ top: 500 }, 1000 );
});

$.when( animations ).done(function() {
    // ALL ANIMATIONS HAVE BEEN DONE IN SEQUENCE
});

Still a lot of function closures but that’s the very nature of Javascript. However, it’s much more natural and a lot more flexible using Deferreds/Promises since you avoid callbacks “inception”.

Answer by Starx

Callback is a friend, dont push it away. There are ways to simplify them. Here is one of them

$('div1').fadeOut('slow', div2)
function div3() { $('div3').fadeOut('slow'); }
function div2() { $('div2').fadeOut('slow', div3); }
April 28, 2012

run/pause CSS animation with jQuery

Question by Ampersand

I would like to start with a paused CSS animation then use jQuery to run the animation for a second before pausing again.

The css is below:

#animation {
  -webkit-animation: one 5s infinite;
  -webkit-animation-play-state: paused;
}

@-webkit-keyframes one {
  0% { .... }
  .....
  100% { .... }
}

It has some complicated keyframes and the aim is that it would play for 1 second to the 20% position then stop.

I tried the jQuery below but it didn’t work:

 $("#click").click(function(){
     $("#animation").css("-webkit-animation-play-state", "running").delay(1000).css("-webkit-animation-play-state", "paused");          
 });

(#click is the div I want to use as the trigger for the animation)

If I remove the delay and subsequent pause it works fine but obviously continues looping.

eg:

 $("#click").click(function(){
     $("#animation").css("-webkit-animation-play-state", "running");            
 });

What would you fine people suggest?

Answer by Starx

jQuery delay() does not function when you are manipulating the css property. Use setTimeOut() instead

$("#click").click(function(){
     $("#animation").css("-webkit-animation-play-state", "running");
     setTimeout(function() { 
       $("#animation").css("-webkit-animation-play-state", "paused");
     }, 1000);
});
April 9, 2012

animate div moving from one place to another

Question by Vijay V

I am designing a potal framework and I have multiple portlets(divs) within the main div.
When I move a div, I want it to move to the top of the page and expand vertically. All of this works, however, I would like to animate the moving part.

this is what my code looks like

$('#smallpotletdiv').prependTo($('#maindiv'));

what would someone that knows more about animation suggest? How would I show the div moving from its current location and attach itself to the new location?

Answer by Starx

Play with the positions using animate and prepend at last. After the prepend is complete, change the values to default

$("#smallpotletdiv").animate({
      top: 300,
      left: 500     
}).prependTo($("#maindiv")).css({
      top: 'auto',
      left: 'auto'
});

Update:

You working codes will look something like this

current.animate({
  top: -30,
  left: -20     
}, 2000, function() {
    current.prependTo(prependToDiv).css({
       top: 'auto',
       left: 'auto'
    });        
});

Check Here

The problem with their execution were that, you didn’t position the element to be movable through left and top. For that an element has to be positioned absolutely i.e. position: absolute.

April 6, 2012

jquery animate height bouncing

Question by g0dl3ss

i made a script that dynamically loads content into a div and whenever the content makes the div’s height bigger or smaller it animates the height to the actual height.

The problem is that it doesn’t only slide up/down it always slides a bit up and then down to the desired height.

I’d like to make it slide directly at the desired height without the “bouncing”.

Here’s part of the script:
main_content.html(html);

main_content.css("height", "auto");
var newContentHeight = main_content.height();
loader_div.hide();
main_content.height(prevContentHeight);
main_content.fadeIn("fast", function() {
    main_content.animate({
        "height": newContentHeight
        }, 300);
    });

The script works, the only problem is that the animation doesn’t slide the div up or down to the desired height, it always slides it a bit up and then down to the desired height.

Is it some kind of wanted animation when using animate height or is there something wrong?
Thanks

edit: console logging newContentHeight(the final height of the div) it looks like it gathers 2 heights, then the animate first goes to one of them and then to the other one that’s why it looks like bouncing. Working on it.

edit2: yes the problem is definitely there, i cleaned up all the code and everything works except that i get 2 attributes from newContentHeight using console.log it looks like the content div that is hidden has 2 heights and those 2 heights are passed to the .animate that’s why it first goes up and then down…
Kinda strange

Answer by g0dl3ss

Couldn’t solve the problem, i modified the script below and now everything works like it should.
http://css-tricks.com/dynamic-page-replacing-content/
It has the exact animation i was looking for(except for a couple of steps easily implementable).

Answer by Starx

I think the problem is not the script, but the system running the script. Replace the time to a bit slower

main_content.animate({
"height": newContentHeight
}, 3000);
March 28, 2012

jQuery function chaining unrelated objects

Question by jim tollan

I have of course searched SO for an answer to my ‘specific’ question but haven’t found anything that allows me to reach my desired goal. Basically, I’d like to be able to chain together function calls with the ability to add a ‘delay’ between those calls being issued. I’m figuring that something along the lines of a setTimeout() chain will be required. However, as these calls are aysnchronys, I obviously can’t simply chain those together and hope for a result. I did see reference to the built in jQuery queue and dequeue functions and figured that something might work based on that. Thus far, I’ve not been able to concoct anything that gets close to my requirement.

I’ve created a very basic example that demonstrates what I’m trying to achieve by chaining here (btw – jsfiddle is being a bit slow today):

http://jsfiddle.net/jimibt/wZeTT/

this uses nested setInterval calls, therefore is nasty and doesn’t scale. My nirvana would be a jquery extension method that had the following syntax (1st param being the function, 2nd param being the setTimout value delay):

$().chain($('#strap1').fadeIn(1300), 500)
     .chain($('#strap2').fadeIn(1300), 500)
     .chain($('#strap3').fadeIn(1300), 500)
     .start();

Now I know that there is a delay() funtion in jquery, but this only works (to my knowledge) as part of a chain against a single selector and thus can’t be used to chain together multiple unconnected elements as per my example. I did see this linked SO question that is CLOSE to what I was hoping for, but still not wrapped up in the way I’d like:

Chaining jQuery animations that affect different elements

Any thoughts??

Answer by Starx

You can use callbacks like this

$('#strap1').delay(500).fadeIn(1300,function(){
    $('#strap2').delay(500).fadeIn(1300,function(){
        $('#strap3').delay(500).fadeIn(1300);
    });
});

Usage [demo]

$('#strap1').delay(500).fadeIn(1300,function(){
    $('#strap2').delay(500).fadeIn(1300,function(){
        $('#strap3').delay(500).fadeIn(1300, function() {
            $('#strapline').css({
                'color': '#fff'
            }).animate({
                'color': color
            }, 3000);            
        });
    });
});
March 17, 2012

jQuery animate() callback not working right with removeClass()

Question by Antonio Vitor

Hey guys I’m working on a jQuery code snippet that’s suppose to remove a class from an object after the animation has been completed. This is what I have so far:

$('.box').hover(function() {
        $(this).stop().addClass('active').animate({ 'margin-top': '-49px' }, 500);
    }, function() {
        $element = $(this);
        $(this).stop().animate({ 'margin-top': '0' }, 500, function() {
            $element.removeClass('active');
        });
    });

The problem is that sometimes when the animation completes the class is not removed. This happens when I move too fast between divs.

You can view an example here in the slider section there are three boxes inside the slider that says ‘City’, ‘House’, and ‘Business’.

Any help is appreciated.

PS the same thing happens on the main navigation, sometimes the sub-nav just hangs there. Here is the code for the navigation:

$('#navigation ul li').hover(function(){
        $("a:eq(0)", this).addClass("hover");
        $(this).find('ul:eq(0)').stop(true, true).slideToggle();
        }, function(){
            $("a:eq(0)", this).removeClass("hover");
            $(this).find('ul:eq(0)').stop(true, true).slideToggle();
        }
    );

Answer by Starx

Change your $element declaration to this

var $element = $(this);
March 12, 2012

Slide to right using .animate () width

Question by Matt Jones

after reading all the questions related to this I still can’t seem to figure out how to make it work for me.

I’ve got a list of social icons that I would like to have slide from left to right when hovering over “Follow Me” and then slide back into hiding when hovered away.

Here is the current code in JSFIDDLE

If you make the fix, can you point out where I made my mistakes? I’m still very new to this. Thanks so much!

Answer by Gary.S

This may not be exactly what you are looking for but is pretty close to what you are asking for. I have stopped using UL and LI’s for the icons and just used a div and spans, this can be changed back if required. The main issue is setting the width to a specific value (percent won’t work).

$('.social-top').hide();

$('#social-grid').mouseenter(function() {
    $('.social-top').show();
    $('.social-top').stop().animate({
        width: 225
    }, 1000);
});

$('#social-grid').mouseleave(function() {
    $('.social-top').stop().animate({
        width: 0
    }, 1000, function() {
        $('.social-top').hide();
    });

});​

This should get you most of the way there. I use show/hide to resolve an issue with 0 width and inline-block elements still being shown.

Example:

http://jsfiddle.net/infiniteloops/NqrKK/13/

Answer by Starx

There are many logical flaws in your code:

  1. Initially you are hiding the container, therefore closing all possibilities of the event ever being triggered
  2. You selector itself is an li item and there is no child <li> inside it.
  3. And Increasing the width property of the element does not take it to left. You need left, right or even padding-left or margin-left

Your syntactical mistake was, the properties to be animated and the time was inside the same curly braces. The correct syntax

$('element').animate(
   {
       //css properties
       left: "50"
   },
   5000 //The time in milliseconds or `fast`, `slow`
);

Use this

$('.social-top li:not(.social-flyout)').hover(function() {
    $('.social-top').animate({
        right: 0
    },"fast"
    );
});

I also gave position: absolute to the .social-top. Here is a working Demo here

...

Please fill the form - I will response as fast as I can!