在默认还原动画为droppable之前播放自定义摇晃效果?

时间:2015-10-13 00:52:04

标签: javascript jquery jquery-ui animation

我的网站上有draggabledroppable元素。我想让draggable元素在用户试图将其放在错误的容器上并且然后恢复它的位置时会发抖。

到目前为止,我的代码可以完成所有操作而不会产生抖动效果:

$('#elementID').draggable({
    revert: 'invalid'
});

$container.droppable({
    accept: function(dropElem){
        return ($(this).attr("meta-ok") === "true"); //return false if it's "wrong" container
    },
...

当我将元素放在“错误”的容器上时,它会恢复元素的位置(好),但在恢复动画发生之前没有“摇动”。

我试图从jQueryUI添加$(...).effect('shake'),但是如何在恢复动画之前播放,然后使用“标准”还原动画(我不是我想替换默认的还原动画,但在它之前插入我的摇动)?

1 个答案:

答案 0 :(得分:1)

revert动画发生在mouseStop上,并嵌套在不同的验证中,这使得很难直接修改。但您可以创建custom draggable并修改还原动画。像这样:

$.widget("ui.customDraggable", $.ui.draggable, {
    _mouseStop: function(event) {

        //If we are using droppables, inform the manager about the drop
        var that = this,
            dropped = false;
        if ($.ui.ddmanager && !this.options.dropBehaviour) {
            dropped = $.ui.ddmanager.drop(this, event);
        }

        //if a drop comes from outside (a sortable)
        if (this.dropped) {
            dropped = this.dropped;
            this.dropped = false;
        }

        if ((this.options.revert === "invalid" && !dropped) || (this.options.revert === "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
            // Original revert is simply animate to original position. You can add whatever you want before
            $(this.helper).effect('shake').animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
                if (that._trigger("stop", event) !== false) {
                    that._clear();
                }
            });
        } else {
            if (this._trigger("stop", event) !== false) {
                this._clear();
            }
        }

        return false;
    },
})

$('#draggable').customDraggable({
    revert: 'invalid',

});

$('#droppable').droppable({
    accept: '#anything'

});

http://jsfiddle.net/6ou82b2k/

或者甚至更好,允许在options中设置要恢复的动画。有点复杂,最容易干扰其他功能,但更灵活。像这样:

$.widget("ui.customDraggable", $.ui.draggable, {
    _mouseStop: function(event) {

        //If we are using droppables, inform the manager about the drop
        var that = this,
            dropped = false;
        if ($.ui.ddmanager && !this.options.dropBehaviour) {
            dropped = $.ui.ddmanager.drop(this, event);
        }

        //if a drop comes from outside (a sortable)
        if (this.dropped) {
            dropped = this.dropped;
            this.dropped = false;
        }

        if ((this.options.revert === "invalid" && !dropped) || (this.options.revert === "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {

           // This allows you to set the animation you want. Since stop event is triggered on animation end, you need the animation to be 'queueable'.
            this.options.revertAnimation.call(this.helper, {originalPosition: this.originalPosition, helper: this.helper});
            $(this.helper).queue( function() {
                if (that._trigger("stop", event) !== false) {
                    that._clear();
                }
            });
        } else {
            if (this._trigger("stop", event) !== false) {
                this._clear();
            }
        }

        return false;
    },



});



$('#draggable').customDraggable({
    revert: 'invalid',
    revertAnimation: function(ui){// this option will be called instead of the normal revert
        $(ui.helper).effect('shake').fadeOut().fadeIn().animate(ui.originalPosition, parseInt(500, 10))
    },
    stop: function(){
        console.log('stopped')
    }

});

$('#droppable').droppable({
    accept: '#anything'

});

http://jsfiddle.net/6ou82b2k/1/

编辑:要仅对无效目标产生影响,它会变得有点复杂。有不同的方法可以做到这一点,其中一种方法是将revert设置为true,让droppable接受draggable并管理丢弃行为。你有dropped变量可以告诉你是否可以在目标上删除拖动,如果是,你决定它是否应该恢复。像这样举例如:

...

        if ((this.options.revert === "invalid" && !dropped) || (this.options.revert === "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
            if (dropped) {
                $(this.helper).effect('shake').animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function () {
                    if (that._trigger("stop", event) !== false) {
                        that._clear();
                    }
                });
            } else if (!dropped) {
                $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function () {
                    if (that._trigger("stop", event) !== false) {
                        that._clear();
                    }
                });
            }
          ...

http://jsfiddle.net/juliengregoire/6ou82b2k/2/