14

オンmouseUpまたはtouchEndそのイベントが発生した要素の参照を取得したい。

デモ

この例では、1つの要素をクリックし、マウスをドラッグして、別の要素の上で離す必要があります。マウスを離すと、その要素の背景が赤に変わります。私のコードはマウスイベントでは正しく機能しますが、タッチデバイスでは機能しません。

touchStart1つの要素上にあり、指が別の要素の上で離されると、最初の要素への参照のみが取得されます。

タッチイベントをマウスイベントとまったく同じように機能させるには、何を変更する必要がありますか?

var isMouseDown = false;    


var panel1 = document.getElementById( 'panel1' );
var panel2 = document.getElementById( 'panel2' );

panel1.onmousedown = onDocumentMouseDown;
panel1.onmouseup = onDocumentMouseUp;
panel1.onmousemove = onDocumentMouseMove;   
panel1.addEventListener( 'touchstart', onDocumentTouchStart, false );
panel1.addEventListener( 'touchmove', onDocumentTouchMove, false );
panel1.addEventListener( 'touchend', onDocumentTouchEnd, false );

panel2.onmousedown = onDocumentMouseDown;
panel2.onmouseup = onDocumentMouseUp;
panel2.onmousemove = onDocumentMouseMove;
panel2.addEventListener( 'touchstart', onDocumentTouchStart, false );
panel2.addEventListener( 'touchmove', onDocumentTouchMove, false );
panel2.addEventListener( 'touchend', onDocumentTouchEnd, false );



function onDocumentMouseDown(event) {
    event.preventDefault();
    panel1.style.background="#2E442E";
    panel2.style.background="#5D855C";      
}

function onDocumentMouseUp(event) {
    event.preventDefault();
    this.style.background="#ff0000";
}

function onDocumentMouseMove( event ) {

}   

function onDocumentTouchStart( event ) {
    event.preventDefault();
    panel1.style.background="#2E442E";
    panel2.style.background="#5D855C";

}

function onDocumentTouchMove( event ) {     

}

function onDocumentTouchEnd( event ) {
    event.preventDefault();         
    this.style.background="#ff0000";        

}
4

3 に答える 3

12

これは取り組むのが楽しい質問でした。それをありがとう。これが私がしたことです。私はあなたのtouchmoveハンドラーをそのように変更しました:

   function onDocumentTouchMove(event) {
    onDocumentTouchMove.x = event.changedTouches[event.changedTouches.length - 1].clientX;
    onDocumentTouchMove.y = event.changedTouches[event.changedTouches.length - 1].clientY;
}

このハンドラーでは、ユーザーが移動した最後の座標を保存しています。おそらく、これは、ユーザーが指、鼻、ナックル、スタイラスなどをタッチ面から離したポイントです。次に、これらの座標をハンドラーで使用して、touchendそれらを囲む要素を見つけます。

    function onDocumentTouchEnd(event) {
    event.preventDefault();
    var elem = document.elementFromPoint(onDocumentTouchMove.x, onDocumentTouchMove.y);
    elem.style.background = "#ff0000";
}

私はこの目的のためにdocument.elementFromPoint(mdnリンク)を利用しました。これは、 CSSOM仕様によって提供されたゴールデンでありながらかなり未知のメソッドの1つです。

これがフィドルです。

于 2013-03-13T12:41:40.793 に答える
0

見たところ、これはタッチイベントの意図された動作です。ただし、回避策があります。

touchStart私はこれを広範囲にテストしていませんが、少なくともtouchEndイベントについてはモバイルSafariで動作するようです。

基本的に、キャプチャフェーズにあるドキュメント上のすべてのタッチイベントをキャプチャします(http://www.w3.org/TR/DOM-Level-3-Events/を参照)。これらのイベントのハンドラーは、この場所でDOM要素を見つけ、「正しい」ターゲットでイベントを再送信します。

touchEndイベントの位置が明確に定義されていないようchangedEventsです。そのため、最後に触れた位置を取得するために配列をクエリする必要がありました。touchMoveこれがイベントなどでそのまま機能するかどうかはわかりません。

function rerouteTouch (evt) {
    if (evt.passthrough) { // Ignore if already rerouted
        return;
    }
    evt.stopPropagation();
    var newevt = document.createEvent('TouchEvent');
    newevt.initTouchEvent (
        evt.type,
        evt.bubbles,
        evt.cancelable,
        evt.view,
        evt.detail,
        evt.screenX,
        evt.screenY,
        evt.clientX,
        evt.clientY,
        evt.ctrlKey,
        evt.altKey,
        evt.shiftKey,
        evt.metaKey,
        evt.touches,
        evt.targetTouches,
        evt.changedTouches,
        evt.scale,
        evt.rotation);
    newevt.passthrough = true; // Only reroute once

    var target;
    var x = (evt.type === 'touchend') ? evt.changedTouches[0].pageX : evt.pageX;
    var y = (evt.type === 'touchend') ? evt.changedTouches[0].pageY : evt.pageY;

    if (document !== (target = document.elementFromPoint(x, y))) {
        target.dispatchEvent(newevt);
    }
}

document.addEventListener( 'touchstart', rerouteTouch, true); // Third arg is true to indicate capture-phase
document.addEventListener( 'touchend', rerouteTouch, true); 

...

// Your event handlers here

これが私にとってモバイルサファリで期待どおりに機能するjsfiddleです:http://jsfiddle.net/DREer/12/

于 2013-03-12T02:25:37.820 に答える
-1

おそらく、jQueryをプログラムに含めることができれば、次のようなことができます。

$('#itemId').on('touchEnd',function(){ this.trigger('mouseUp') });

箱から出してすぐに使用できるjQueryがこのイベントをサポートしているかどうかはわかりませんが、いつでもjQuerymovilを試すことができます。お役に立てば幸いです。

于 2012-07-12T05:30:23.247 に答える