如何停止jQuery动画插件?有一个更好的方法来做到这一点

时间:2011-05-13 04:32:53

标签: jquery jquery-plugins css3

过去一周我生病了,非常无聊,所以我决定自学一些关于编写jQuery插件的东西。我在大约半小时内把这个放在一起,当你按住i(Phone | Pad | Pod Touch)中的特定图标时,它会模仿“摆动”效果。为了让它开始“摇摆”很容易,我只使用了CSS3过渡。

http://area51.thedrunkenepic.com/wiggle/

但是,让图标停止摆动已经证明有点困难。我是创建jQuery插件的新手,所以我不是100%清楚如何保存收集对象的状态,然后稍后通过回调或事件修改所述状态。

所以,我结束了创建一个用于收集所有匹配对象的数组。然后我使用这个数组来或多或少地维护应用了摆动效果的对象的状态。

即使它有效,它似乎过于低效,这使我相信有更好的,也许是内在的(在jQuery中),这样做的方式。

有人可以看看这个简单的插件并告诉我,如果有的话,我可以做什么?我不是要求有人改进我的代码。也许现实世界中的一个实际例子或一些可靠的文档就足够了。

非常感谢你! :)

插件来源:http://area51.thedrunkenepic.com/wiggle/wiggle.jquery.js

2 个答案:

答案 0 :(得分:3)

您可以将setTimeout结果存储在每个对象中,如下所示:

object.timeout = setTimeout(function(){
methods.rotate(object, step+1);
}, options.delay);

然后在你的停止功能中,在它上面调用clearTimeout,如下所示:

clearTimeout(object.timeout);

包含这些更改的完整插件如下:

(function($){
var rotatingObjectCollection = [];

$.fn.wiggle = function(method, options) {
    options = $.extend({
        rotateDegrees: ['1','2','1','0','-1','-2','-1','0'],
        delay: 35
    }, options);

    var methods = {
        rotate: function(object, step){
            if(step === undefined) {
                step = Math.floor(Math.random()*options.rotateDegrees.length);
            }

            var degree = options.rotateDegrees[step];
            $(object).css({
                '-webkit-transform': 'rotate('+degree+'deg)',
                '-moz-transform': 'rotate('+degree+'deg)'
            });

            if(step == (options.rotateDegrees.length - 1)) {
                step = 0;
            }

            object.timeout = setTimeout(function(){
                methods.rotate(object, step+1);
            }, options.delay);
        },
        stop: function(object) {
            $(object).css({
                '-webkit-transform': 'rotate(0deg)',
                '-moz-transform': 'rotate(0deg)'
            });

            clearTimeout(object.timeout);
            object.timeout = null;
        }
    };

    this.each(function() {
        if((method == 'start' || method === undefined) && !this.timeout) {
            methods.rotate(this);
        } else if (method == 'stop') {
            methods.stop(this);
        }
    });
    return;
}
})(jQuery);

我不知道将自定义数据存储在这样的对象中是否是一种好习惯,但是嘿,它的工作原理是:)

答案 1 :(得分:1)

我建议您在再次设置动画之前检查目标元素是否已经摆动,因为用户可以将您的开始按钮发送垃圾邮件,并且您的元素会存储动画。
动画不会是理想的动画,浏览器可能会崩溃 另一件事是保持可链接性:你的插件破坏了jquery链,而且你不能使用$(selector).wiggle().doSomethingElse();这样的东西,因为你的插件在执行后没有返回任何内容(return;)。 通过少量修改,插件看起来像:

(function($){
$.fn.wiggle = function(method, options) {
    options = $.extend({
        rotateDegrees: ['1','2','1','0','-1','-2','-1','0'],
        delay: 35
    }, options);

    var methods = {
        rotate: function(object, step){
            if(step === undefined) {
                step = Math.floor(Math.random()*options.rotateDegrees.length);
            }

            var degree = options.rotateDegrees[step];
            $(object).css({
                '-webkit-transform': 'rotate('+degree+'deg)',
                '-moz-transform': 'rotate('+degree+'deg)'
            });

            if(step == (options.rotateDegrees.length - 1)) {
                step = 0;
            }

            object.timeout = setTimeout(function(){
                methods.rotate(object, step+1);
            }, options.delay);
            $(object).data('wiggling',true);
        },
        stop: function(object) {
            $(object).css({
                '-webkit-transform': 'rotate(0deg)',
                '-moz-transform': 'rotate(0deg)'
            });
            clearTimeout(object.timeout);
            $(object).data('wiggling',false);
        }
    };

    this.each(function() {
        if($(object).data('wiggling') == true && (method == 'start' || method === undefined)) {
            methods.rotate(this);
        } else if (method == 'stop') {
            methods.stop(this);
        }
    });
    return this;
}
})(jQuery);