I made a small test code using the jquery transit plugin for animations.
The purpose of the script is to have a photo of a tower make a flip 90 degrees toward the user, switch to another tower image, and flip another 90 degrees to lay flat on the screen. The issue is that after the first 90 degree flip, the image disappears entirely until the for loop has concluded before doing the final flip as the second image. I'm looking to have it flip continuously until the loop is finished.
I imagine this has something to do with closures and scope...
Javascript:
$(function() {
for (var i = 0; i < 10; i++) {
$('#test_flip')
.css('background-image', 'url("tower1.jpg")')
.transition({
rotateY: '90deg'
}, function() {
$('#test_flip')
.css('background-image', 'url("tower2.jpg")')
.transition({
rotateY: '180deg'
});
});
};
});
jsfiddle: http://jsfiddle.net/ce9b9aja/
The issue lies in the fact that the for loop calls .transition
10 times consecutively. The calls are queued
in the jQuery queue (which is done behind the scenes by transit.js), but they are not queued in the order you're expecting.
Take the following example:
$(function () {
$('#test').transition({x:40}, function () {
$(this).transition({y:40});
})
$('#test').transition({scale:0.5}, function() {
$(this).transition({skewX:"50deg"});
});
});
#test {
width: 10em;
height: 10em;
background-color: gray;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://ricostacruz.com/jquery.transit/jquery.transit.min.js"></script>
<div id="test"></div>
In this example, the first transition x:40
will be executed instantly because there is no queue. Despite the fact that it is executed instantly, since it is an animation, it will be using some form of setTimeout
or setInterval
and will not be completed in the transition
method call. Consequently, the scale:0.5
transition will be called while the x:40
transition is still animating, which will put it in the queue it before y:40
is put in the queue.
Therefore, the queue order is
x:40 -> scale:0.5 -> y:40 -> skewX:50deg
Similarly, your code is producing the following queue:
rotateY:90deg -> ... -> rotateY:90deg -> rotateY:180deg -> ... -> rotateY:180deg
Thus your code's behavior. It rotates the image 90deg
first, then it does it 9 more times, which doesn't change anything visually (hence the "pause"). Then it changes the image and rotates it 180deg
and does that 9 more times also.
One solution could be to create a recursive function using the callback of the .transition
function. An example is implemented below:
$(function() {
FlipMe($('#test_flip'), "http://i.imgur.com/tYYtwbi.jpg", "http://i.imgur.com/G4CvJpc.jpg", 10)
});
function FlipMe($el, image1, image2, times) {
$el.css('background-image', 'url("'+image1+'")')
.transition({rotateY: '90deg'}, function() {
$el.css('background-image', 'url("'+image2+'")')
.transition({rotateY: '180deg'}, function() {
if(times > 0) {
FlipMe($el, image2, image1, times - 1);
}
});
});
}
Updated fiddle here: http://jsfiddle.net/ce9b9aja/1/
The code above exclusively uses callback functions to dictate the order of events. When the first transition is completed, the callback function will "queue" the next transition, which will be executed instantly since nothing else will be in the queue. And so on.