2014-09-02 1 views
0

Я сделал небольшой тестовый код, используя плагин jquery transit для анимации.jquery animate callback не выполняется до последнего цикла

Целью сценария является то, что фотография башни делает поворот на 90 градусов по направлению к пользователю, переключается на другое изображение башни и переворачивает еще 90 градусов, чтобы лежать на экране. Проблема в том, что после первого 90-градусного флип изображение полностью исчезает до тех пор, пока цикл for не завершится, прежде чем делать окончательный флип в качестве второго изображения. Я ищу, чтобы он переворачивался непрерывно, пока цикл не закончится.

Я полагаю, это что-то делать с замыканиями и рамки ...

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/

ответ

0

Проблема заключается в том, что цикл вызывает .transition 10 раз подряд. Вызовы - queued в очереди jQuery (что делается за кулисами by transit.js), но они не поставлены в очередь в том порядке, в котором вы ожидаете.

Рассмотрим следующий пример:

$(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>

В этом примере первый переход x:40 будет выполняться мгновенно, потому что нет никакой очереди. Несмотря на то, что он выполняется мгновенно, так как это анимация, он будет использовать в форме setTimeout или setInterval и не будет быть выполнен в вызове метода transition. Следовательно, будет вызываться переход scale:0.5, в то время как переход x:40 все еще оживляет, который помещает его в очередь до того, как y:40 будет помещен в очередь.

Поэтому порядок очереди

x:40 -> scale:0.5 -> y:40 -> skewX:50deg 

Аналогично, ваш код производит следующую очередь: поведение

rotateY:90deg -> ... -> rotateY:90deg -> rotateY:180deg -> ... -> rotateY:180deg 

Таким образом вашего кода. Сначала он поворачивает изображение 90deg, затем он делает это еще 9 раз, что ничего не меняет визуально (отсюда и «пауза»). Затем он меняет изображение и поворачивает его 180deg и делает это еще 9 раз.

Одним из решений может быть создание рекурсивной функции с использованием обратного вызова функции .transition. Пример реализуется следующим образом:

$(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); 
        } 
       }); 
    }); 
} 

Обновлено скрипки здесь: http://jsfiddle.net/ce9b9aja/1/

Код выше исключительно использует функцию обратного вызова, чтобы диктовать порядок событий. Когда первый переход завершен, функция обратного вызова будет «очереди» следующего перехода, который будет выполняться мгновенно, поскольку в очереди не будет ничего другого. И так далее.

+0

Сладкий человек. Это хорошее решение! – tomc