4

I'm using JQuery UI to addClass(), and later to removeClass().

If removeClass() is called before addClass() completes, it queues up and executes later. This is not ideal, I'd rather have the removeClass() execute immediately from the current CSS values.

If I invoke stop() just before add/removeClass(), animation seems permanently 'frozen' at the moment of the stop() call, though the add/removeClass() callback still fires.

Just the JS here:

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"); }

All the rest here: http://jsfiddle.net/mmstM/42/

This seems like it would be a common issue but haven't found any good info on SO or elsewhere...note this is for JQuery UI, not core.

4

4 回答 4

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);
});

您可以在此处查看工作示例其中有一个额外的技巧,可以从 CSS 加载宽度/高度值并将它们存储在对象中以模仿 add/removeClass() 语法。

于 2012-09-02T17:24:34.553 回答
1

问题是当您停止动画时,您的类不会应用于元素。它现在处于意料之外的状态。所以删除类没有效果,因为类没有应用于元素。

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

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

于 2012-09-02T17:27:23.077 回答
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"); });
});

​这里有多个状态的工作示例。

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

我会接受@sudowned 的回答,因为它对带领我到这里最有帮助。

于 2012-09-02T19:23:35.483 回答
1

为什么不搜索样式表,获取 cssText,然后将其(我不确定如何以最佳方式执行此操作)解析为 JS 对象?

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

animateToSelector是一个可以实现这两个功能的 jQuery 插件。

主要问题是它不灵活。我无法为(比如说)鼠标悬停的元素的子元素设置动画。理想情况下,我们应该简单地获取我们可以传递给的样式对象animate()

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

于 2012-10-31T07:53:49.847 回答