web-dev-qa-db-ja.com

タッチデバイス用のJavascriptドラッグアンドドロップ

タッチデバイスで動作するドラッグアンドドロッププラグインを探しています。

「ドロップ可能な」要素を許可する jQuery UIプラグイン と同様の機能が欲しい。

jqtouchプラグイン はドラッグをサポートしていますが、ドロップはサポートしていません。

ここ は、iPhone/iPadのみをサポートするドラッグアンドドロップです。

Android/iosで動作するドラッグアンドドロッププラグインの方向を教えてくれる人はいますか?

...または、ドロップ可能性のためにjqtouchプラグインを更新することが可能かもしれません。それはすでにAndriodとIOSで実行されています。

ありがとう!

115
joe

マウスイベントを必要なタッチに変換する追加のライブラリを使用して、ドラッグアンドドロップにJquery UIを使用できます。推奨されるライブラリは https://github.com/furf/jquery-ui-touchです-punch 、これにより、Jquery UIからのドラッグアンドドロップがタッチデバイスで機能するはずです。

または、私が使用しているこのコードを使用して、マウスイベントをタッチに変換し、魔法のように機能します。

function touchHandler(event) {
    var touch = event.changedTouches[0];

    var simulatedEvent = document.createEvent("MouseEvent");
        simulatedEvent.initMouseEvent({
        touchstart: "mousedown",
        touchmove: "mousemove",
        touchend: "mouseup"
    }[event.type], true, true, window, 1,
        touch.screenX, touch.screenY,
        touch.clientX, touch.clientY, false,
        false, false, false, 0, null);

    touch.target.dispatchEvent(simulatedEvent);
    event.preventDefault();
}

function init() {
    document.addEventListener("touchstart", touchHandler, true);
    document.addEventListener("touchmove", touchHandler, true);
    document.addEventListener("touchend", touchHandler, true);
    document.addEventListener("touchcancel", touchHandler, true);
}

そして、document.readyでinit()関数を呼び出すだけです

ここ から見つかったコード

254
ryuutatsuo

これを使用し、「クリック」機能を維持したい人は(ジョンランドヒーがコメントで述べているように)、わずかな変更を加えるだけで実行できます。

いくつかのグローバルを追加します。

var clickms = 100;
var lastTouchDown = -1;

次に、switch文を元の文から次の文に変更します。

var d = new Date();
switch(event.type)
{
    case "touchstart": type = "mousedown"; lastTouchDown = d.getTime(); break;
    case "touchmove": type="mousemove"; lastTouchDown = -1; break;        
    case "touchend": if(lastTouchDown > -1 && (d.getTime() - lastTouchDown) < clickms){lastTouchDown = -1; type="click"; break;} type="mouseup"; break;
    default: return;
}

「clickms」を好みに合わせて調整することもできます。基本的には、クリックをシミュレートするための「タッチスタート」に続いて「タッチエンド」がすぐに見られるだけです。

21
E.Z. Hart

上記のコードをありがとう! -私はいくつかのオプションを試しましたが、これがチケットでした。 preventDefaultがiPadでのスクロールを妨げているという問題がありました-現在、ドラッグ可能なアイテムをテストしており、これまでのところうまく機能しています。

if (event.target.id == 'draggable_item' ) {
    event.preventDefault();
}
12
gregpress

gregpress answer と同じ解決策がありましたが、ドラッグ可能なアイテムはidではなくクラスを使用しました。うまくいくようです。

var $target = $(event.target);  
if( $target.hasClass('draggable') ) {  
    event.preventDefault();  
}
10
Eric

私が知っている古いスレッド.......

@ryuutatsuoの答えの問題は、「クリック」に反応する必要がある入力またはその他の要素(入力など)もブロックすることです。そのため、このソリューションを作成しました。このソリューションにより、任意のタッチデバイス(またはコンピューター)でのmousedown、mousemove、およびmouseupイベントに基づく既存のドラッグアンドドロップライブラリを使用できるようになりました。これはクロスブラウザソリューションでもあります。

私はいくつかのデバイスでテストしましたが、高速に動作します(ThreeDubMediaのドラッグアンドドロップ機能と組み合わせて( http://threedubmedia.com/code/event/drag も参照)。 jQueryソリューションであるため、jQueryライブラリでのみ使用できます。 jQuery 1.5.1を使用しました。これは、一部のより新しい関数がIE9以上で適切に動作しないためです(テストされていませんjQueryの新しいバージョン)。

前に任意のドラッグまたはドロップ操作をイベントに追加します最初にこの関数を呼び出す必要があります

simulateTouchEvents(<object>);

次の構文を使用して、すべてのコンポーネント/子を入力用にブロックしたり、イベント処理を高速化することもできます。

simulateTouchEvents(<object>, true); // ignore events on childs

これが私が書いたコードです。物事の評価を高速化するために、いくつかの素敵なトリックを使用しました(コードを参照)。

function simulateTouchEvents(oo,bIgnoreChilds)
{
 if( !$(oo)[0] )
  { return false; }

 if( !window.__touchTypes )
 {
   window.__touchTypes  = {touchstart:'mousedown',touchmove:'mousemove',touchend:'mouseup'};
   window.__touchInputs = {INPUT:1,TEXTAREA:1,SELECT:1,OPTION:1,'input':1,'textarea':1,'select':1,'option':1};
 }

$(oo).bind('touchstart touchmove touchend', function(ev)
{
    var bSame = (ev.target == this);
    if( bIgnoreChilds && !bSame )
     { return; }

    var b = (!bSame && ev.target.__ajqmeclk), // Get if object is already tested or input type
        e = ev.originalEvent;
    if( b === true || !e.touches || e.touches.length > 1 || !window.__touchTypes[e.type]  )
     { return; } //allow multi-touch gestures to work

    var oEv = ( !bSame && typeof b != 'boolean')?$(ev.target).data('events'):false,
        b = (!bSame)?(ev.target.__ajqmeclk = oEv?(oEv['click'] || oEv['mousedown'] || oEv['mouseup'] || oEv['mousemove']):false ):false;

    if( b || window.__touchInputs[ev.target.tagName] )
     { return; } //allow default clicks to work (and on inputs)

    // https://developer.mozilla.org/en/DOM/event.initMouseEvent for API
    var touch = e.changedTouches[0], newEvent = document.createEvent("MouseEvent");
    newEvent.initMouseEvent(window.__touchTypes[e.type], true, true, window, 1,
            touch.screenX, touch.screenY,
            touch.clientX, touch.clientY, false,
            false, false, false, 0, null);

    touch.target.dispatchEvent(newEvent);
    e.preventDefault();
    ev.stopImmediatePropagation();
    ev.stopPropagation();
    ev.preventDefault();
});
 return true;
}; 

機能:最初は、シングルタッチイベントをマウスイベントに変換します。イベントが、要素上または要素内の要素によって引き起こされているかどうかをチェックします。 input、textareaなどの入力要素の場合、翻訳をスキップします。または、標準のマウスイベントがそれに関連付けられている場合、翻訳もスキップします。

結果:ドラッグ可能な要素上のすべての要素はまだ機能しています。

ハッピーコーディング、Gretz、Erwin Haantjes

8
Codebeat