2012-07-11 8 views
13

Na mouseUp lub touchEnd Chcę uzyskać odwołanie do elementu, w którym zdarzenie miało miejsce.Jak uzyskać touchEnd zachowywać się tak jak MouseUp?

Demo

W tym przykładzie, trzeba kliknąć na jeden element, przeciągnij myszą i wydany przez inny element. Po zwolnieniu myszy tło tego elementu zmieni kolor na czerwony. Mój kod działa poprawnie dla zdarzeń myszy, ale nie na urządzeniach dotykowych.

Gdy touchStart znajduje się na jednym elemencie, a palec zostaje zwolniony na innym elemencie, otrzymuję tylko odniesienie do pierwszego elementu.

Co muszę zmienić, aby wydarzenia dotykowe działały dokładnie tak, jak zdarzenia myszy?

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";   

} 
+0

jakie urządzenia dotykowe wypróbowałeś (znaczy) – shareef

+0

** Podobne pytanie ** [Jak dowiedzieć się o aktualnym zdarzeniu event.target zdarzenia javascript touchmove?] (Http://stackoverflow.com/q/3918842/351708) – Rohit

Odpowiedz

11

To było pytanie zabawa do rozwiązania. Dziękuję za to. Oto, co zrobiłem. Mam zmodyfikowany obsługi touchmove jako takie:

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

W tym obsługi ja ratuję ostatni koordynować, że użytkownik przeniósł się do. Najprawdopodobniej jest to punkt, w którym użytkownik wziął palec, nos, golonka, rysik itp. Z powierzchni dotykowej. Współrzędne te następnie używam w programie obsługi dla touchend, aby znaleźć element, który je otacza.

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

mam wykorzystane document.elementFromPoint(mdn link) do tego celu. Jest to jedna z tych złotych, ale dość nieznanych metod dostarczonych nam przez CSSOM spec. To jest .

+1

Świetne znalezisko! Mogę potwierdzić, że działa to na karcie Samsung Galaxy Tab z Chrome. –

+0

Działa również na operę, w przeglądarce Android i chrom na moim x. – zeusdeux

+0

tak .. myślę, że to dobre rozwiązanie .. :) ale nie wiem, że wsparcie dla elementuFromPoint .. – Sarath

-1

Być może, jeśli można to jQuery do programu można zrobić coś takiego:

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

Nie jestem pewien, czy jQuery po wyjęciu z pudełka obsługuje tej imprezy, ale zawsze można spróbuj jQuery movil, mam nadzieję, że pomogło

+0

nie mogę zawierać jquery ... ale to również da taki sam wynik. – Sarath

+0

@isaac 'this' tutaj nadal będzie elementem, w którym' touchstart' został zwolniony, więc nie jest dobrym rozwiązaniem. – zeusdeux

0

Z tego, co się wydaje, jest to zamierzone zachowanie dla zdarzeń dotykowych. Jednak mam obejście!

Nie testowałem tego w znacznym stopniu, ale wygląda na to, że działa na mobilnym Safari co najmniej od touchStart i touchEnd zdarzeń.

Zasadniczo zamierzamy zrobić wszystkie zdarzenia związane z dotykiem na dokumencie, ponieważ są one w fazie przechwytywania (patrz http://www.w3.org/TR/DOM-Level-3-Events/). Program obsługi tych zdarzeń znajdzie element DOM w tej lokalizacji i ponownie wyśle ​​zdarzenie z "poprawnym" celem.

Wygląda na to, że pozycja zdarzeń touchEnd nie jest dobrze zdefiniowana, więc musiałem wysłać zapytanie do tablicy changedEvents, aby uzyskać ostatnią dotkniętą pozycję. Nie jestem pewien, czy to działa tak jak dla zdarzeń touchMove i innych.

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 

Oto jsfiddle który działa zgodnie z oczekiwaniami na telefon safari dla mnie: http://jsfiddle.net/DREer/12/