似乎每个50-100 jsfiddle更新都将我带到stackoverflow社区,以帮助解决我创建的新问题!所以谢谢!
背景:我有几个包含动画的函数,在上一个函数完成后将要触发这些函数。在一些帮助和研究下,我开始使用$ .when和.promise()在每个函数的最初非常丑陋的回调字符串和setTimeouts上控制这些东西。
我的难题是:在某个时候,用户可能想暂停所有内容,然后在闲暇时再次恢复。我似乎无法添加此功能!
我可以使用$('div:animated')。stop()暂停所有动画,但这是临时的,因为.promise()仍然可以解析!有什么办法可以覆盖这种行为?任何可能有助于暂停和恢复的重组都容易实现吗?
[明天,我打算沿着将所有动画添加到代理对象队列的路径,但是不确定在新对象上创建全局队列与现有结构的配合效果如何。我也打算添加一些布尔值以检查值是否关闭,然后不要调用函数或设置动画。我不确定这些解决方案中的任何一个是否是我应该采取的适当方向?
预览这篇文章后,我也倾向于学习如何重构嵌套的开始按钮功能!
对实现暂停和恢复功能的任何指导将不胜感激。
下面的代码已大大简化,每个函数包含更多元素和动画。
JS:
$('#start').click( function() {
// run a and wait one second, when done run b and wait 1 second...
a().delay(100).promise().done( function(){
b().delay(100).promise().done( function(){
c().delay(100).promise().done( function(){
d().delay(100).promise().done( function(){
e().delay(100).promise().done( function(){
f().delay(100).promise().done( function(){
alert('all done!');
});
});
});
});
});
});
});
$('#reset').click( function() {
$('.box').css({
top: '0px'
});
});
$('#pause').click( function() {
$('div:animated').stop();
});
function a() {
return $('.box1').animate({top: '100px'}, 1000, function(){
$('.box1').animate({top: '50px'}, 1000);
});
return $('.box6').animate({top: '200px'}, 4000);
}
function b(){
return $('.box2').animate({top: '100px'}, 1000);
}
function c(){
return $('.box3').animate({top: '100px'}, 1000, function(){
$('.box3').animate({top: '50px'}, 1000);
});
}
function d(){
return $('.box4').animate({top: '100px'}, 1000);
}
function e(){
return $('.box5').animate({top: '100px'}, 1000, function(){
$('.box5').animate({top: '50px'}, 1000);
});
}
function f(){
return $('.box6').animate({top: '100px'}, 1000);
}
html&CSS
<button id='start'>animate</button>
<button id='reset'>Reset</button>
<button id='pause'>pause</button>
<div class='boxes'>
<div class='box box1'></div>
<div class='box box2'></div>
<div class='box box3'></div>
<div class='box box4'></div>
<div class='box box5'></div>
<div class='box box6'></div>
</div>
.boxes{position: relative}
.box{width: 40px; height: 40px; background-color: green; position:absolute;}
.box1{left: 0px;}
.box2{left: 60px;}
.box3{left: 120px;}
.box4{left: 180px;}
.box5{left: 240px;}
.box6{left: 300px;}
编辑您的回答提供了我一直在寻找的学习经验;我真的很感谢您的参与!我提出的示例可能无法充分展示现实世界中的问题,因为提出的答案不允许同时播放多个动画?我至少不认为?例如,box1和box2可以同时移动,或者当box3触发时,box6也会移动。我实现的最初的非常丑陋的承诺系统使用了许多功能,因为每个功能都由许多动画组成。建议的答案将如何实现?
EDIT2有两个答案,charlietfl允许我轻松添加同时触发的辅助函数;很重要。 Alnitak拥有一种构造数组并将其应用于动画的优雅方法,该方法非常容易更改动画类型(fadeOut(),fadeIn())。
因此,我试图将两者结合起来,以便可以为使用Alnitaks数组格式的辅助动画创建嵌套数组:
['.box1', 'animate', { top: '50px'}, 1000],
总之,我仍在研究所有答案,但与charlietfls的答案接近/接近。向其添加Alnitak的数组,或向Alnitak的数组添加charlietfl的嵌套。
这比我以前打算的还要强烈;感谢您的贡献和可学习的代码。...非常有用!
允许多个同时动画的jQuery方法非常好,但是当您的动画都是连续的时,那就太过分了。
我建议创建一组动画描述,然后在一个简单的循环中一次只调用一个动画描述。
每个描述都需要知道要动画的元素,要调用的函数以及函数参数是什么。
然后暂停动画只是一个不通过循环的问题:
function next() {
if (!animating) return;
var a = list.shift();
if (a) {
var el = a[0];
var fn = a[1];
var args = a.slice(2);
$.fn[fn].apply($(el), args).promise().done(next);
} else {
alert('all done!');
}
};
请参见http://jsfiddle.net/alnitak/ANRa3以获取演示。
而不是使用animate
的回调调用次要动画,如果您链接animate().delay().animate()
,则可以返回次要动画的承诺。
我的解决方案使用嵌套的对象数组,因此您可以根据需要轻松地在一个序列中添加任意数量的动画。诀窍是创建一个组中所有promise的数组,并使用该数组确定完整动画组何时完成。
样本数据:
var animations = [
/* first group array */
[ { "sel": ".box1","main": {"css": {"top": "100px"},"dur": 1000},
"secondary": {"delay": 100,"css": {"top": "50px"},"dur": 1000 }
},
{"sel": ".box2","main": {"css": {"top": "100px"},"dur": 1000}},
{"sel": ".box4","main": {"css": {"top": "100px"},"dur": 1000}},
{ "sel": ".box5","main": {"css": {"top": "100px"},"dur": 1000},
"secondary": {"delay": 100,"css": {"top": "50px"},"dur": 1000 }
}
],
/* second group array */
[ { "sel": ".box3","main": {"css": {"top": "100px"},"dur": 1000},
"secondary": {"delay": 100,"css": {"top": "50px"},"dur": 1000 }
},
{"sel": ".box4","main": {"css": {"top": "100px"},"dur": 1000}}
]
];
JS:
var curr = -1;
var paused = false;
function animateBoxes() {
if (paused) {
return;
}
//curr = (curr + 1 < animations.length) ? curr + 1 : 0;
curr=curr+1;
if( !animations[curr]){
alert('DONE!!');
return;
}
/* array of animation deffereds*/
var anims = [];
$.each(animations[curr], function(i, currAnim) {
var anim = boxAnimate(currAnim);
anims.push(anim)
});
$.when.apply(null, anims).done(function() {
animateBoxes();
});
}
$('#start').click(function() {
paused = false;
animateBoxes();
});
$('#reset').click(function() {
curr = -1;
stopanimation();
$('.box').css({
top: '0px'
});
});
$('#pause').click(function() {
stopanimation();
});
function stopanimation() {
paused = true;
$('div:animated').stop(true, true);
}
function boxAnimate(obj) {
var $el = $(obj.sel),
anim;
if (obj.secondary) {
/* chain animate & delay to get promise for last effect */
anim = $el.animate(obj.main.css, obj.main.dur)
.delay(obj.secondary.delay)
.animate(obj.secondary.css, obj.secondary.dur)
} else {
anim = $el.animate(obj.main.css, obj.main.dur)
}
return anim;
}