jQuery UI - 可拖动的'snap'事件

fgu*_*len 12 jquery-ui jquery-ui-draggable

我正在寻找绑定snap事件的方法.

当我拖着一个元素在我的面和可拖动的元素被抢购的声明对齐位置我想触发一个事件.

像这样的东西:

$(".drag").draggable({
  snap: ".grid",
  snaped: function( event, ui ) {}
});
Run Code Online (Sandbox Code Playgroud)

奖金点:与所述的参考.grid,其中所述元件可拖动元件折断.

Fré*_*idi 27

draggable控件不公开这样的事件开箱即用(还).您可以修改它并维护自定义版本,或者更好地从中派生新的窗口小部件并在那里实现新事件.然而,还有第三种方式.

这个问题,我们知道小部件在其snapElements属性中存储了一个潜在的"可抢占"元素的数组.反过来,此数组中的每个元素都会公开一个snapping属性,即true如果可拖动助手当前被捕捉到此元素,false否则(助手可以同时捕捉到多个元素).

snapElements阵列为每个更新drag事件,所以它始终是最新的drag处理程序.从那里,我们只需要draggable使用data()从关联元素中获取窗口小部件实例,并调用其_trigger()方法来引发我们自己的snapped事件(实际上是dragsnapped在引擎盖下).顺带一提,我们可以$ .extend()ui一个jQuery对象包装的抓拍元素对象:

$(".drag").draggable({
    drag: function(event, ui) {
        var draggable = $(this).data("draggable");
        $.each(draggable.snapElements, function(index, element) {
            if (element.snapping) {
                draggable._trigger("snapped", event, $.extend({}, ui, {
                    snapElement: $(element.item)
                }));
            }
        });
    },
    snap: ".grid",
    snapped: function(event, ui) {
        // Do something with 'ui.snapElement'...
    }
});
Run Code Online (Sandbox Code Playgroud)

但是,上面的代码仍然可以改进.就目前而言,只要可拖动的助手仍然对齐元素,就会snapped触发每个drag事件(发生很多)的事件.此外,捕捉结束时不会触发任何事件,这不是很实际,并且会导致这些事件成对发生(snapped-in,snapped-out).

幸运的是,snapElements数组是持久的,所以我们可以使用它来存储状态.我们可以snappingKnown为每个数组元素添加一个属性,以便跟踪我们已经触发了snapped该元素的事件.此外,我们可以使用它来检测自上次调用以来元素已被抢断并作出相应的反应.

请注意,snapped-out下面的代码不是引入另一个事件,而是选择在对象中传递一个额外的snapping属性(反映元素的当前状态)ui(当然,这只是一个优先事项):

$(".drag").draggable({
    drag: function(event, ui) {
        var draggable = $(this).data("draggable");
        $.each(draggable.snapElements, function(index, element) {
            ui = $.extend({}, ui, {
                snapElement: $(element.item),
                snapping: element.snapping
            });
            if (element.snapping) {
                if (!element.snappingKnown) {
                    element.snappingKnown = true;
                    draggable._trigger("snapped", event, ui);
                }
            } else if (element.snappingKnown) {
                element.snappingKnown = false;
                draggable._trigger("snapped", event, ui);
            }
        });
    },
    snap: ".grid",
    snapped: function(event, ui) {
        // Do something with 'ui.snapElement' and 'ui.snapping'...
        var snapper  = ui.snapElement.attr("id"),snapperPos = ui.snapElement.position(),
            snappee  = ui.helper.attr("id"),     snappeePos = ui.helper.position(),
            snapping = ui.snapping;
        // ...
    }
});
Run Code Online (Sandbox Code Playgroud)

您可以在此处测试此解决方案.

最后,另一项改进可能是使snapped事件可以取消,因为drag事件是.为了实现这一点,我们必须false从我们的drag处理程序返回一个_trigger()返回的调用false.但是,在实现此操作之前,您可能需要三思而后行,因为取消对管理单元或管理单元的拖动操作在一般情况下看起来不像用户友好的功能.

更新:从jQuery UI的1.9起,data()密钥成为小部件的全名,由破折号替代点.因此,上面用于获取窗口小部件实例的代码变为:

var draggable = $(this).data("ui-draggable");
Run Code Online (Sandbox Code Playgroud)

代替:

var draggable = $(this).data("draggable");
Run Code Online (Sandbox Code Playgroud)

在1.9中仍然支持使用非限定名称但不推荐使用,并且支持将在1.10中删除.

  • 应该注意的是,"$(this).data("draggable")"已在较新版本中重命名为$(this).data("ui-draggable")... (2认同)