I have a problem with animate loop. There is an object i want to move in a special way and do it in loop. Are there any native options to make it? I have this:
$(function () {
function runIt() {
$('#div').show("slow");
$('#div').animate({"marginLeft":"300px"},8000);
$('#div').animate({"marginLeft":"0px"},8000);
$('#div').hide("slow", runIt);
}
runIt();
});
But it seems not so pretty.
That's the proper way to queue animations. However, there's some things that can be made to your code to make it a bit snappier and prettier:
Store a reference to the selected element in a local variable to speed up execution (less queries made to the DOM)
Clean it up by removing unnecessary quotes for object properties
Sizing is measured in pixels per default so we can use pure integers instead
The named function can be replaced with a immediately invoked anonymous function and then use arguments.callee as the callback
Here's an example showcasing the above changes:
$(function () {
var element = $("#div");
(function(){
element
.show("slow")
.animate({ marginLeft: 300 }, 1000)
.animate({ marginLeft: 0 }, 1000)
.hide("slow", arguments.callee);
}());
});
You can also do it in a more advanced way by creating your own plugin to use custom queues. I created a small fiddle a while back when I was fooling around with animation queues.
More about immediately invoked function expression can be read on Ben "Cowboy" Alman's blog.
That is how I would do it. The only suggestion I would make is to use chaining for nicer code and so the jquery object doesn't get created every time.
$(function () {
function runIt() {
$('#div').show("slow")
.animate({"marginLeft":"300px"},8000)
.animate({"marginLeft":"0px"},8000)
.hide("slow", runIt);
}
runIt();
});
Related
I made a very simple plugin for my personal use that allows animated rotations in jQuery.
And I added callback functions.
If the rewind parameter is true, the rotation is undone and then, a callback.
If it's false, the callback is immediate after the rotation.
I had to do this because, for some reason, the .promise().done(function(){ ... }) is called before complete: of animate()
So I had to skirt this.
Now the problem is that if I target multiple elements, the callback is called for each element. 'cause I use an each function I presume. But I want only one callback for the whole animation.
Here is the fiddle
How to do this please? Thx !
PS: I saw a similar question here : jQuery $.animate() multiple elements but only fire callback once but not applying because of the .promise().done() issue. And I don't want to add a variable, I want to understand ^^
You could try using the index of each and only call the callback if it is the first element
Something like:
return this.each(function(i) {
....
....
complete: function() {
i==0 && a.callback && a.callback()
}
I need the functionality of animating the z-index property of a specific HTML object. I've been able to achieve this animation in two ways that both have their difficulties/drawbacks. Successfully answering this question for me will fix one of the following two issues:
The first is by adapting the JQuery animate command with the step functionality outlined here by the accepted answer:
jQuery's $('#divOne').animate({zIndex: -1000}, 2000) does not work?
The problem with this method for me is that the $('#obj').stop(); command cannot prematurely end the animation when done in this way. It always finishes unless I destroy the object I'm working with and create a new one (which causes blinking obviously). If anyone knows of a way to properly stop a step animation like this, or a work-around for the issue, I'd love to see it.
var div = $('#obj');
$({z: ~~div.css('zIndex')}).animate({z: [-2000, 'linear']}, {
step: function() {
div.css('zIndex', ~~this.z);
},
duration: 10000
});
The second is using a setInterval loop on 20 MS (a speed that is sufficient for my needs) to simply adjust the z-index to what it should be at that point of the "animation". This works great for a few moments, then something causes it to stop working suddenly. The code still runs through the $('#obj').css('z-index', val); line, and val is changing, but it no longer updates the object in the DOM. I've tried it on slower timer settings as well with identical results. Anyone know why JQuery might suddenly no longer be able to set the Z-Index?
function () move {
if (!(MoveX == 0 && MoveY == 0))
{
$('#obj').css('z-index', val);
}
}
$('#obj').stop() doesn't work for you because the animation isn't being performed on $('#obj').
It is being performed on the object $({z: ...}) (with a custom step function). This means you should do something like
var anim = $({z: ~~div.css('zIndex')}).animate({z: [-2000, 'linear']}, {
step: function() {
div.css('zIndex', ~~this.z);
},
duration: 10000
});
// sometime later
anim.stop();
See this demo.
Edit For what it's worth, here is the same demo using an animation interval. I see a syntax error in your second snippet: the function declaration should be
function move() { ...
I assume that's a typo since your code wouldn't even parse. Other than that, I'm not sure why that solution didn't work for you.
I have a function to perform an animation using setTimeout functions, structured as follows:
animation: function() {
//first
setTimeout(function(){
makeObject({ ... }); // this makes '#object .secondary' on the DOM
}, 500);
//second
setTimeout(function(){
...
}, 1000);
//third
setTimeout(function(){
$('#object .secondary').doSomething();
}, 1500);
}
I am creating an object associated with the '.secondary' CSS class in the first setTimeout function, then I am trying to select the object and manipulate it using the class name in the third function. However, the object remains unchanged after the third function executes, and I receive the error "Undefined is not a function". I think this is due to the fact that the setTimeouts execute at the same time, so the secondary object does not yet exist to be selected by the third function. So my question is this: how do I manipulate the secondary object from the third setTimeout function?
The timeouts on their own shouldn't be an issue. The 3rd will start around 1 second after the 1st.
But, the error you mentioned would be. Based on your comment:
The calls are actually d3 via d3.select('#object').selectAll('.secondary').fadeOut(50);
It's because D3's Selections, that d3.select() and .selectAll() return, aren't related to jQuery and won't have its methods.
You'll have to either convert the collection from d3 to jQuery before using .fadeOut().
jQuery( d3.select('#object').selectAll('.secondary') ).fadeOut(50);
Or, use jQuery throughout the statement, as you'd suggested doing in your snippet:
jQuery('#object .secondary').fadeOut(50);
How about setting the 2nd&3rd Timeout in the previous one?
E.G.
animation:function() {
setTimeout(function() {
makeObject(…);
setTimeout(function() {
...
setTimeout(function() {
$('#object .secondary').doSomething();
},500);
},500);
},500);
};
I just want to animate element during a game of cards, but the problem is that when I use the animate function the code is continue to run.
I tried with the promise() and done() function, but for some reason it doesn't help.
Here is what I did:
$(document).ready( function() {
$(".demoCard").animate({
"margin-top": '-150'
}, 1000, "easeInSine", function() {
$(".demoCard").remove();
});
});
According to the api documentation. Your callback is correct. Try updating your jQuery api. Maybe you are using an outdated version. If that doesn't work, try removing your easing argument. JQuery might be trying to use the easing argument as a callback function. If you need your easing, make sure you have jQuery UI installed and loaded. Otherwise, jQuery won't recognize the easing, and try to use easeInOutSine as the callback function.
I want to extend the $.fn object in order to have a delay between my jquery commands :
like this working (and quite long) code :
$('.d').delay(1000).queue(
function ()
{
$(this).css('background-color', 'green');
$(this).dequeue();
}).delay(1000).queue(function ()
{
$(this).css('background-color', 'red');
$(this).dequeue();
});
a working sample is here : JSBIN
So I tried this :
My code at jsbin
$.fn.myWait = function (ms)
{
return this.queue(
function ()
{
var _self = this;
setTimeout(function ()
{
$(_self).dequeue();
}, ms);
})
};
invoking :
$('.d').myWait(1000).css('background-color', 'red').myWait(1000).css('background-color', 'green');
But it doesnt work.
What am I doing wrong ?
p.s.
I did read this similar solution, but if I remove the animation part and use only css , it also doesnt work.
The .css() does not get queued on the animation queue by itself, that's why you needed to put it in a callback in your first snippet. In the second snippet, it is called immediately (even though there's timeout waiting in the queue - just as like you called .delay()). Instead, you would need to use an .animate() call with a zero-duration.
For allowing the syntax which you wanted, you will need to take a step further. Have a look at the jQuery timing plugin and how their magic works.
I doubt you can do it in this way. You need to defer execution of those attribute changes, which means you shall store said code in individual functions.