播放自定义震动效果之前的默认还原动画为可放下

Play custom shaking effect before default revert animation for droppable?

本文关键字:还原 默认 动画 放下 自定义 播放      更新时间:2023-09-26

我有一个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'),但是如何在还原动画之前播放,然后使用"标准"还原动画(我不想替换默认的还原动画,但在它之前插入我的震动)?

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并管理drop上的行为。您有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/