之前工作的时候,为了要在画面上加入一些动态效果,并且让他循序自动执行。所以有这方考量:
1.使用 setTimeout 或是 setInterval
2.利用 animate 可以延迟的方式重新呼叫
3.使用 queue
首先我尝试了第一个方法,将要执行的东西,包成 function,然后利用 setTimeout 或是 setInterval 呼叫。很好,他可以运作了,但是我遇到另一个问题,当我需要中断他,或是暂停的时候,用这种方式呼叫就相对的麻烦。因为我加入了动态(Effect)的效果,如果直接强制中断,那该怎么知道他做到 function 中的哪一段呢?
后来我换了第二个方法,使用 animate 就可以延迟,也可以利用 callback 回呼自己,更有 stop() 可用。那,第二个问题来了,当我 stop() 之后,需要重新开始时,只能重新呼叫一次那个 callback 并把整个程序全部重做一次。如果没有其他的事件时,他是可以很顺利的走完,但倘若参杂了其他的事件,那就会有干扰的状况发生。其实所谓干扰的状况,并不是 API 本身的问题,我相信那是可以人为控制的,就是我写的太烂才会发生干扰的意思啦。
后来我在 API 中找到了 queue 这个东西。先来简单介绍一下他是做甚么用的。他的作用是将你要执行的 function 丢到阵列里面去依序执行。举个简单的例子,倘若我们要做一个动态效果:
$('#div-a').animate({ left: "+=20" }, 1000, function() { $('#div-a').animate({ top: "+=30" }, 1000, function() { $('#div-a').animate({ left: "+=50" }, 1000, function() { alert('动态效果结束了'); }); });});
这种东西如果一多起来,跟噩梦没两样。如果使用 queue 来做的话,那么我可以改写成这样:
var myAnimate = function() { $('#div-a').animate({ left: "+=20"}, 1000).queue(function() { $(this).dequeue(); } ); $('#div-a').animate({ top: "+=30"}, 1000).queue(function() { $(this).dequeue(); } ); $('#div-a').animate({ left: "+=50"}, 1000).queue(function() { alert('动态效果结束了'); } );}; myAnimate();
这样就可以了。如果要让他循序,就把最后一个 alert 换成 myAnimate(); 就可以达到循序。其实 queue 可以把他看做是一个阵列,而 dequeue 则是呼叫阵列中下一个元件出来执行。
// 将要循序执行的程序写成阵列var FUNC = [ // animate 结束的 callback 再次呼叫 myAnimate,等于告诉他,请执行下一个 queue 元件 function() { $('#div-a').animate({ left: "+=20"}, 1000, myAnimate); }, function() { $('#div-a').animate({ top: "+=30"}, 1000, myAnimate); }, function() { $('#div-a').animate({ left: "+=50"}, 1000, myAnimate); }, function() { alert('动态效果结束了'); }]; // 将 dequeue 指定给变数 myAnimate 并包装成 functionvar myAnimate = function() { $('#div-a').dequeue("myAnimation");} // 把 FUNC 这个阵列指定给名称为 myAnimation$('#div-a').queue("myAnimation", FUNC); // 呼叫 myAnimate,由于呼叫了 dequeue,他便会开始从 myAnimation 的第一个程序开始执行myAnimate();
这样就是 queue 的做法,更详尽的资料可以查看 jQuery 的未压缩格式关于 queue 的部分。
再来,在 jQuery 1.4 中,新加入了一个新的方法 .clearQueue,他的作用是用于清除(或是取消)所有从 queue 中所加入的任何 function,换句话说,如果你在 queue 的 callback 中有使用任何程序的话,是可以使用 clearQueue 把他强制给取消的。
另外,官方有说他可以停止 fx 相关的动态效果,类似于使用 stop() 的效果,但是我是用过的之后觉得,动态效果还是用 stop() 去停止比较妥当啦。所以还是来个例子,以上面的例子来说,如果我中途要暂停某一个动态效果,那么我必须要这么做:
// 我们用一个 click 来停止他$('stop-button').click(function() { $('#div-a').stop();});
这样,动态效果就会停止了。但是,你有发现什么问题吗?那就是,你要重新使用他的时候,就得重新在呼叫一次 myAnimate(); 这个程序。
// 我们用一个 click 来启动他$('start-button').click(function() { myAnimate();});
看出问题了吗?如果没有 clearQueue 的话,你重新启动他的时候,他并不会接着之前暂停的地方去执行,而是直接跳过上一个 queue,直接执行下一个 queue 内容!这样知道差别了吗?所以,我们需要做这样的修改:
// 我们用一个 click 来停止他,并且清除这次的 queue 执行$('stop-button').click(function() { $('#div-a').clearQueue(); $('#div-a').stop();});
这样一来,如果我们重新呼叫 myAnimate(); 重新启动的时候,就会从上次的结果继续下去。