12

snapイベントをバインドする方法を探しています。

サーフェス上で要素をドラッグしていて、ドラッグ可能な要素が宣言されたスナップ位置にスナップされたときに、イベントをトリガーしたいと考えています。

このようなもの:

$(".drag").draggable({
  snap: ".grid",
  snaped: function( event, ui ) {}
});

ボーナス ポイント:ドラッグ可能な要素がスナップ.gridされた要素への参照。

4

2 に答える 2

27

ウィジェットは、そのままでは (まだ)そのdraggableようなイベントを公開しません。それを変更してカスタム バージョンを維持するか、より良い方法として、そこから新しいウィジェットを派生させ、そこに新しいイベントを実装することができます。ただし、3 つ目の方法があります。

この質問から、ウィジェットが潜在的に「スナップ可能な」要素の配列をそのsnapElementsプロパティに格納していることがわかります。次に、この配列の各要素は、ドラッグ可能なヘルパーが現在この要素にスナップされている場合と、そうでない場合 (ヘルパーは同時に複数の要素にスナップできる)のsnappingプロパティを公開します。truefalse

snapElements配列はイベントごとに更新されるため、ハンドラーdragでは常に最新です。dragそこdraggableから、関連付けられた要素からdata()_trigger()を使用してウィジェット インスタンスを取得し、そのメソッドを呼び出して独自のsnappedイベントを発生させるだけです (実際dragsnappedには内部で)。渡す際に、スナップされた要素をラップする jQuery オブジェクトを使用してオブジェクトを$.extend()することができます。ui

$(".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'...
    }
});

ただし、上記のコードはまだ改善の余地があります。現状では、ドラッグ可能なヘルパーが要素にスナップされている限り、すべてのイベント (頻繁に発生するsnapped)に対してイベントがトリガーされます。さらに、スナップの終了時にイベントがトリガーされないため、これはあまり実用的ではなく、このようなイベントがペアで発生するという規則 ( 、) を損ないます。dragsnapped-insnapped-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;
        // ...
    }
});

このソリューションは、こちらでテストできます。

最後に、もう 1 つの改善点として、イベントがそうであるように、snappedイベントをキャンセル可能dragにすることが考えられます。これを実現するには、への呼び出しの 1 つが returnの場合falsedragハンドラーから_trigger()戻る必要がありますfalse。ただし、スナップインまたはスナップアウトでのドラッグ操作のキャンセルは、一般的に非常にユーザーフレンドリーな機能とは思えないため、これを実装する前によく考えてください。

更新: jQuery UI 1.9 以降、キーdata()はウィジェットの完全修飾名になり、ドットがダッシュに置き換えられます。したがって、ウィジェット インスタンスを取得するために上記で使用したコードは次のようになります。

var draggable = $(this).data("ui-draggable");

それ以外の:

var draggable = $(this).data("draggable");

非修飾名の使用は 1.9 で引き続きサポートされていますが、推奨されておらず、1.10 でサポートが削除されます。

于 2012-07-24T13:25:05.943 に答える
1

jquery-ui 1.10.0では、上記のコードは機能しません。代わりに、ドラッグ機能は次のとおりです。

drag: function(event, ui) {
  var draggable = $(this).data("ui-draggable")
  $.each(draggable.snapElements, function(index, element) {
    if(element.snapping) {
      draggable._trigger("snapped", event, $.extend({}, ui, {
        snapElement: $(element.item)
      }));
    }
  });
}
于 2013-02-10T17:14:44.563 に答える