如何停止JQuery UI addClass / removeClass?

时间:2012-09-02 17:05:54

标签: javascript jquery jquery-ui animation addclass

我正在使用JQuery UI来添加类(),然后使用removeClass()。

如果在addClass()完成之前调用removeClass(),它会排队并稍后执行。这不是理想的,我宁愿立即从当前的CSS值执行removeClass()。

如果我在add / removeClass()之前调用stop(),则在stop()调用时动画似乎永久“冻结”,尽管add / removeClass()回调仍然会触发。

这里只是JS:

var obj = $("#obj");
obj.addClass("obj");

$("#add").click(function(){
    //obj.addClass("adder", 2000, "easeInOutCubic", onAdded);
    obj.stop().addClass("adder", 2000, "easeInOutCubic", onAdded);
});

$("#remove").click(function(){
    //obj.removeClass("adder", 2000, "easeInOutCubic", onRemoved);
    obj.stop().removeClass("adder", 2000, "easeInOutCubic", onRemoved);
});

function onAdded () { console.log("added"); }
function onRemoved () { console.log("removed"); }

其余所有内容:http://jsfiddle.net/mmstM/42/

这似乎是一个常见的问题,但在SO或其他地方没有找到任何好的信息...请注意这是针对JQuery UI ,而不是核心。

4 个答案:

答案 0 :(得分:7)

问题正在发生,因为即使删除了类后,为动画生成的插页式大小规则仍然存在于元素的style属性中。

我们可以通过以下方式轻松解决这个问题:

obj.stop().attr("style", "").removeClass("adder", 2000, "easeInOutCubic", onRemoved);

但是,这会导致动画中相当大的跳跃,因为类操作的缓动不会考虑元素样式 - 这就是为什么简单地清除队列的原因没用。我担心,对此的快速解决方案非常难看:使用.animate()方法代替,并将类中的样式移动到jQuery,如下所示:

$("#add").click(function(){
    //obj.addClass("adder", 2000, "easeInOutCubic", onAdded);
    obj.stop().animate({
        width: '200px',
        height: '80px',
    }, 2000, "easeInOutCubic", onAdded);
});

$("#remove").click(function(){
    //obj.removeClass("adder", 2000, "easeInOutCubic", onRemoved);
    obj.stop().animate({
        width: '40px',
        height: '40px',
    }, 2000, "easeInOutCubic", onRemoved);
});

您可以查看工作示例here,,并使用加载黑客来加载CSS中的宽度/高度值,并将它们存储在对象中以模仿add / removeClass()语法。

答案 1 :(得分:1)

问题在于,当您停止动画时,您的类不会应用于该元素。它现在处于一个意料之外的状态。因此删除该类没有任何效果,因为该类未应用于该元素。

你最好的选择是做这样的事情:

http://jsfiddle.net/nickaknudson/8UnRd/

答案 2 :(得分:1)

这是我最终结束的地方:

$.fn.extend({
    animateClass: function (propNames, className, speed, easing, callback) {
        var $store = $("<div>").css('display', 'none').addClass(className);
        $("body").append($store);

        var i=0, len=propNames.length, name, propsMap={};
        for (i; i<len; i++) {
            name = propNames[i];
            propsMap[name] = $store.css(name);
        }
        $store.remove();

        this.stop().animate(propsMap, speed, easing, callback);
    }
});

var $obj = $("#obj");
$("#bigger").click(function(){
    $obj.animateClass(["width", "height"], "bigger", 2000, "easeOutQuad", function () { console.log("BIG"); });
});

具有多个状态here的工作示例。

这不是最漂亮的事情,因为它需要传递一个css属性列表才能在动画中使用,而不是只使用样式表中的所有内容,但是我找不到一种方法来分隔样式表中指定的属性。所有其他样式已经在animateClass()中创建的虚拟“$ store”div上。

我会接受@ sudowned的答案,因为这对我来说是最有帮助的。

答案 3 :(得分:1)

为什么不搜索样式表,抓住cssText,并将它解析(我不知道如何以最佳方式执行此操作)到JS对象中?

通过比较CSS规则的document.stylesheets[i].rules成员,可以使用selectorText数组搜索样式表。

一个同时执行这两个操作的jQuery插件是animateToSelector

主要问题是它不灵活。我无法为一个(比如)moused over元素的孩子制作动画。理想情况下,我们应该简单地获取可以传递给animate()

的样式对象

这种解决方案很棒,因为jQuery-UI addClass不支持多个选择器(AFAIK)。