Синхронная анимация JQuery
Во многих случаях я хочу, чтобы анимация выполнялась синхронно. Особенно, когда я хочу сделать серию последовательных анимаций.
Есть ли простой способ сделать синхронный вызов функции jQuery animate
?
Единственный способ, по которому я думал, - установить флаг true, когда анимация закончена, и ждать этого флага.
Ответы
Ответ 1
jQuery не может создавать синхронные анимации.
Помните, что JavaScript работает в потоке пользовательского интерфейса браузера.
Если вы создадите синхронную анимацию, браузер замерзнет, пока анимация не закончится.
Зачем вам это нужно?
Вероятно, вы должны использовать параметр обратного вызова jQuery и продолжить свой код метода в обратном вызове, например:
function doSomething() {
var thingy = whatever;
//Do things
$('something').animate({ width: 70 }, function() {
//jQuery will call this method after the animation finishes.
//You can continue your code here.
//You can even access variables from the outer function
thingy = thingy.fiddle;
});
}
Это называется замыканием.
Ответ 2
Я думаю, вам стоит взглянуть на метод jQuery queue().
Репликация jQuery не только для функции queue() doc jQuery не блокирует пользовательский интерфейс и фактически ставит их в очередь друг за другом.
Он также предоставляет возможность сделать ваши анимации и вызовы функций последовательными (это мое лучшее понимание того, что вы подразумеваете под "синхронным" ), например:
$("#myThrobber")
.show("slow") // provide user feedback
.queue( myNotAnimatedMethod ) // do some heavy duty processing
.hide("slow"); // provide user feedback (job
myNotAnimatedMethod() { // or animated, just whatever you want anyhow...
// do stuff
// ...
// tells #myThrobber ("this") queue your method "returns",
// and the next method in the queue (the "hide" animation) can be processed
$(this).dequeue();
// do more stuff here that needs not be sequentially done *before* hide()
//
}
Это, конечно, избыточное с асинхронной обработкой; но если ваш метод на самом деле является простым старым синхронным javascript-методом, это может быть способ сделать это.
Надеюсь, что это поможет, и извините за мой бедный английский...
Ответ 3
jQuery предоставляет обратный вызов "step" для своего метода .animate(). Вы можете подключиться к этому, чтобы выполнять синхронную анимацию:
jQuery('#blat').animate({
// CSS to change
height: '0px'
},
{
duration: 2000,
step: function _stepCallback(now,opts) {
// Stop browser rounding errors for bounding DOM values (width, height, margin, etc.)
now = opts.now = Math.round(now);
// Manipulate the width/height of other elements as 'blat' is animated
jQuery('#foo').css({height: now+'px'});
jQuery('#bar').css({width: now+'px'});
},
complete: function _completeCallback() {
// Do some other animations when finished...
}
}
Ответ 4
Я согласен с @SLaks на этом. Вы должны использовать обратные вызовы jQuery для данных анимаций для создания вашей синхронной анимации. Вы можете по существу взять все, что у вас есть, для своей текущей анимации и разбить ее так:
$yourClass = $('.yourClass');
$yourClass.animate({
width: "70%"
}, 'slow', null, function() {
$yourClass.animate({
opacity: 0.4
}, 'slow', null, function() {
$yourClass.animate({
borderWidth: "10px"
});
});
});
Ответ 5
Я наткнулся на это http://lab.gracecode.com/motion/
Действительно прост в использовании и отлично работает в сочетании с jquery.
ИЗМЕНИТЬ
Ссылки кажутся мертвыми. Если я правильно слежу за тропами, то этот архив обратного пути, код находится в https://github.com/feelinglucky/motion
Ответ 6
jQuery может создавать синхронные анимации. Проверьте это:
function DoAnimations(){
$(function(){
$("#myDiv").stop().animate({ width: 70 }, 500);
$("#myDiv2").stop().animate({ width: 100 }, 500);
});
}
Ответ 7
Вот модуль, который я собрал некоторое время назад, чтобы помочь в запуске анимации последовательно.
Использование:
var seq = [
{ id: '#someelement', property:'opacity', initial: '0.0', value:'1.0', duration:500 },
{ id: '#somethingelse', property:'opacity', value:'1.0', duration: 500 }
];
Sequencer.runSequence(seq);
var Sequencer = (function($) {
var _api = {},
_seq = {},
_seqCount = 0,
_seqCallback = {};
function doAnimation(count, step) {
var data = _seq[count][step],
props = {};
props[data.property] = data.value
$(data.id).animate(props, data.duration, function() {
if (step+1 < _seq[count].length) {
doAnimation(count, ++step);
} else {
if (typeof _seqCallback[count] === "function") {
_seqCallback[count]();
}
}
});
}
_api.buildSequence = function(id, property, initial, steps) {
var newSeq = [],
step = {
id: id,
property: property,
initial: initial
};
$.each(steps, function(idx, s) {
step = {};
if (idx == 0) {
step.initial = initial;
}
step.id = id;
step.property = property;
step.value = s.value;
step.duration = s.duration;
newSeq.push(step);
});
return newSeq;
}
_api.initSequence = function (seq) {
$.each(seq, function(idx, s) {
if (s.initial !== undefined) {
var prop = {};
prop[s.property] = s.initial;
$(s.id).css(prop);
}
});
}
_api.initSequences = function () {
$.each(arguments, function(i, seq) {
_api.initSequence(seq);
});
}
_api.runSequence = function (seq, callback) {
//if (typeof seq === "function") return;
_seq[_seqCount] = [];
_seqCallback[_seqCount] = callback;
$.each(seq, function(idx, s) {
_seq[_seqCount].push(s);
if (s.initial !== undefined) {
var prop = {};
prop[s.property] = s.initial;
$(s.id).css(prop);
}
});
doAnimation(_seqCount, 0);
_seqCount += 1;
}
_api.runSequences = function() {
var i = 0.
args = arguments,
runNext = function() {
if (i+1 < args.length) {
i++;
if (typeof args[i] === "function") {
args[i]();
runNext();
} else {
_api.runSequence(args[i], function() {
runNext();
});
}
}
};
// first we need to set the initial values of all sequences that specify them
$.each(arguments, function(idx, seq) {
if (typeof seq !== "function") {
$.each(seq, function(idx2, seq2) {
if (seq2.initial !== undefined) {
var prop = {};
prop[seq2.property] = seq2.initial;
$(seq2.id).css(prop);
}
});
}
});
_api.runSequence(arguments[i], function (){
runNext();
});
}
return _api;
}(jQuery));