JQuery анимированный обратный вызов не выполняется до последнего цикла
Я сделал небольшой тестовый код, используя плагин JQuery для анимации.
Цель сценария - сделать фотографию башни, повернуть ее на 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/
1 ответ
Проблема заключается в том, что вызовы цикла for .transition
10 раз подряд. Звонки queued
в очереди jQuery (что делается негласно транзитом.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/
Приведенный выше код использует исключительно функции обратного вызова для определения порядка событий. Когда первый переход завершен, функция обратного вызова "поставит в очередь" следующий переход, который будет выполнен мгновенно, поскольку в очереди больше ничего не будет. И так далее.