2011-08-17 19 views
17

Gram z touchstart i touchend wydarzeń na moim iPhone. Zbudowałem przykładową stronę, która ma div, która po dotknięciu i przewinięciu strony powinna zwrócić współrzędne y pozycji początkowej i końcowej.jQuery (Swipe vs. Touch) pageX i pageY wracają 0

Link: http://jsbin.com/ibemom/2

jQuery:

var touchStartPos; 

$('.theDiv') 
    .bind('touchstart', function(e){ 
    touchStartPos = e.pageY; 
    }) 
    .bind('touchend', function(e){ 
    alert(touchStartPos + ' | ' + e.pageY) 
    }) 

Kiedy załadować tej strony na moim iPhone, jednak uderzył nieczysto i utrzymuje raportowanie zarówno wartości jak zero. Czy ktoś widzi coś złego w tym, co mam?

UPDATE:

natknąłem tego kawałka kodu w projekcie jQuery mobile: https://github.com/jquery/jquery-mobile/issues/734

Komentarz go z niej wyciągnął:

// (in iOS event.pageX and event.pageY are always 0) 

To nie powiedzieć dlaczego to prawda, ale przynajmniej znalazłem kogoś, kto widzi to samo. Przeszukuje przykładowy kod na tej stronie, aby sprawdzić, czy istnieje rozwiązanie.

UPDATE II:

Cóż, po spojrzeniu przez przykładowy kod w linku powyżej, wygląda to tak powróci rzeczywistą wartość:

e.originalEvent.touches[0].pageY 

Połów jest, ja sobie teraz sprawę, że nie jest całkiem potrzebuję. Zwraca przesunięcie Y obszaru, który dotknąłem w obiekcie, do którego dołączyłem, do IN RELACJI DO DOKUMENTU HTML ... zamiast do okna przeglądarki.

Moim celem jest dowiedzieć się, gdzie na ekranie dotyk zaczął i gdzie się zakończył ... a następnie porównać wartości. Jeśli są one trochę inne, to przypuszczamy, że wykonano przesunięcie ... raczej niż dotyk.

UPDATE III:

Ja również znaleźć odnośniki do tych przykładów:

e.originalEvent.touches[0].pageX 

event.targetTouches[0].pageY 

Choć nie wydaje się uzyskać te do pracy albo. Oba zwracają niezdefiniowane błędy.

UPDATE IV:

Wygląda na to jedno rozwiązanie jest śledzenie offsetu() w samym dokumencie. Mogę zastosować zdarzenie touchend do dokumentu, a następnie sprawdzić jego przesunięcie.

Problem polega na tym, że moje zdarzenie touchend najpierw uruchomi się na elemencie na mojej stronie, a następnie uruchomi go na dokumencie (bulgotanie). Tak więc nie jestem w stanie określić, czy to był dotyk czy przesunięcie, ZANIM potrzebuję dowiedzieć się, co zrobić w przypadku zdarzenia touchend.

Nadal rozważając ten jeden ...

+0

dziwne, nie knwo o sieciach komórkowych, ale działa dobrze z kliknięć http://jsfiddle.net/nH2PU/ – Sinetheta

+1

miałem nadzieję, że to nie będzie to dużo Stumper. ;) –

+0

To samo zdarza się w Androidzie (2.2.2) – NoBugs

Odpowiedz

19

Ok szybka odpowiedź brzmi: nie można wykryć dotyk gdy palec opuści ekran (touchend).

Mój pierwszy przykład dowodzi, że: http://jsfiddle.net/Y4fHD/

Teraz do obejścia. Lub nazwij to, co chcesz. Może to ma sens, nie wykrywa się na zdarzeniu touchend, ponieważ zakończyło się dotknięcie .

Bind handler na razie touchmove: http://jsfiddle.net/Y4fHD/1/

var endCoords = {}; 
$(document.body).bind("touchmove", function(event) { 
    endCoords = event.originalEvent.targetTouches[0]; 
}); 

a następnie użyć zmiennej endCoords do zdeterminowanej ostatnim naciśnięciu

$(document.body).bind("touchend", function(event) { 
    $('p').text("Your end coords is: x: " + endCoords.pageX + ", y: " + endCoords.pageY); 
}); 

Ok spróbować po prostu wybierz swoje urządzenie! Wtedy błąd nadal będzie widoczny: dlaczego? Ponieważ nie poruszyłeś swojego dotyku.

Jeśli wszyscy gotowi w touchstart definiuje zmienną endCoords jesteśmy tam: http://jsfiddle.net/Y4fHD/2/

var endCoords = {}; 
$(document.body).bind("touchstart touchmove", function(event) { 
    endCoords = event.originalEvent.targetTouches[0]; 
}); 

a następnie użyć zmiennej endCoords do zdeterminowanej ostatnim naciśnięciu

$(document.body).bind("touchend", function(event) { 
    $('p').text("Your end coords is: x: " + endCoords.pageX + ", y: " + endCoords.pageY); 
}); 

Teraz spróbuj dotknij urządzenie!

Niektóre końcowe noty będą: wprowadzić do zmiennych: startCoords i endCoords następnie wykorzystać te w przypadku touchend: http://jsfiddle.net/Y4fHD/3/

var startCoords = {}, endCoords = {}; 
$(document.body).bind("touchstart", function(event) { 
    startCoords = endCoords = event.originalEvent.targetTouches[0]; 
}); 
$(document.body).bind("touchmove", function(event) { 
    endCoords = event.originalEvent.targetTouches[0]; 
}); 
$(document.body).bind("touchend", function(event) { 
    $('p').text("Your touch on the axis: " + Math.abs(startCoords.pageX-endCoords.pageX) + "x, " + Math.abs(startCoords.pageY-endCoords.pageY) + "y"); 
}); 

Uwaga:
Żadne z powyższych przykładów są testowane, ma nadzieję, że działa!
Math.abs daje mi wartość bezwzględną liczby np -5 staje 5

+0

Zauważyłem, że w ostatnim przykładzie napisałeś bezwzględną wartość osi Y dwa razy na linii "$ (" p '). "Tekst (" Twój dotyk na oś ... ". – Arabam

+0

@Arabam To jest teraz naprawione.Aby pomyśleć, że po dwóch latach ten typ błędu zostanie znaleziony :) – andlrc

+0

Dziękuję za wzmiankę o" event.originalEvent "- w Androidzie oryginalne zdarzenie tłumiło właściwość targetTouches i łamanie wszystkiego! Co ciekawe, nie było problemu z systemem iOS, co utrudniło debugowanie. – jocull

1

Oto, co działa dla mnie ....

$('.someClass').bind('touchmove',function(e){ 
    e.preventDefault(); 
    var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0]; 
    var elm = $(this).offset(); 
    var x = touch.pageX - elm.left; 
    var y = touch.pageY - elm.top; 
    if(x < $(this).width() && x > 0){ 
     if(y < $(this).height() && y > 0){ 
       //your code here 
     } 
    } 
}); 
2

Nie jest uproszczoną kawałek kodu Jestem przyzwyczajony do wykrywania przesuwając gesty dla .myelement, w oryginale było galeria suwak

$(function() { 
    var diff, tchs, del = 150, 
    clk = function(el){ 
     if (typeof(tchs) !== 'object') return; //we have nothing to do 
     if ((diff - tchs[tchs.length - 1].pageX) < 0) { //swipe right 

     } 
     else if ((diff - tchs[tchs.length - 1].pageX) > 0) { //swipe left 

     } 
    }; 
    $('.myelement').bind('touchstart touchmove', function(ev){ 
      var oev = ev.originalEvent, el = $(this); 
      switch(ev.type.charAt(5)){ 
       case 's': //touch start 
        diff = oev.pageX; 
        window.setTimeout(clk, del, el); 
       break; 
       case 'm': //touch move 
        tchs = oev.touches; 
       break; 
      } 
    }); 
}); 

UPD: Nawiasem mówiąc, kiedy użyłem wersji MobiOne 2.0.0M2 Software Testing Center to było umieścić touchend wartość pageX jak oczekiwano, więc to brzmi ba d implementacja, która może być łatwa do zmylenia, jeśli nie masz szybkiego dostępu do prawdziwego urządzenia.

UPD2: ok, zainspirowany pozytywnymi opiniami :) zrealizował nieco skomplikowaną wersję, która pozwala wykryć prawe, lewe, górne i dolne przesuwanie, to jednak musi być wyczyszczone, ale masz pomysł. Odpowiedź

$(function() { 
    var ftch, // first touch cache 
    lck = Math.sin(Math.PI/4); //lock value, sine of 45 deg configurable 

    var defSwipeDir = function (el, tchs) { // need define swaping direction, for better UX 
     if (typeof (tchs) !== 'object') return 0; // check if there was any movements since first touch, if no return 0 
     var ltch = tchs[tchs.length - 1], // last touch object 
      dx = ltch.pageX - ftch.pageX, 
      dy = ltch.pageY - ftch.pageY, 
      hyp = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2)), 
      sin = dy/hyp, 
      cos = dx/hyp, 
      dir; 

     if (Math.abs(cos) >= lck) { // left or right swape 
      dir = cos > 0 ? 'r' : 'l'; 
     } else { // up or down 
      dir = sin < 0 ? 'u' : 'd'; 
     } 
     el.trigger('swipe', dir); // trigger custom swipe event 
     return dir; // and return direction too 
    } 

    $('.myelementTouchDetection').on('touchstart touchmove swipe', function (ev, d) { 
     var oev = ev.originalEvent, 
      myelementTouchDetection = $(this), 
      dir; // you may know swipes on move event too 

     switch (ev.type) { 
      case 'touchstart': 
       ftch = oev; 
       break; 
      case 'touchmove': 
       dir = defSwipeDir(myelementTouchDetection, oev.touches); 
       return false // cancel default behaiviour 
       break; 
      case 'swipe': 
       switch (d) { 
        case 'r': // swipe right 
         console.log('swipe right'); 
         break; 
        case 'l': // swipe left 
         console.log('swipe left'); 
         break; 
        case 'u': // swipe up 
         console.log('swipe up'); 
         break; 
        case 'd': // swipe down 
         console.log('swipe down'); 
         break; 
       } 
       break; 
     } 
    }) 
}); 
2

null, przede pracował wielki dla mnie, poza tym, że nie można przypisać startCoords do endCoords w funkcji touchstart związany. Następnie wskazują ten sam obiekt, aby po zaktualizowaniu endCoord, tak samo jak startCoords. Po uruchomieniu eventu touchend, startCoords zawsze będzie równy EndCoords.

Zaktualizowany kod poniżej. To działało dla mnie na iPadzie 3 przy użyciu przeglądarki Safari na iOS 6.0. Edytowano również w celu naprawienia błędu matematycznego i wyświetlania oraz usunięcia Math.abs() wewnątrz funkcji związanej z dotykiem. Dodano także wywołanie event.preventDefault() wewnątrz funkcji związanej z touchmove, tak aby działały również w przeglądarce Google Chrome na iOS.

var startCoords = {}, endCoords = {}; 

$(document.body).bind("touchstart", function(event) { 
    endCoords = event.originalEvent.targetTouches[0]; 
    startCoords.pageX = event.originalEvent.targetTouches[0].pageX; 
    startCoords.pageY = event.originalEvent.targetTouches[0].pageY; 
}); 

$(document.body).bind("touchmove", function(event) { 
    event.preventDefault(); 
    endCoords = event.originalEvent.targetTouches[0]; 
}); 

$(document.body).bind("touchend", function(event) { 
    $('p').text("Your touch on the axis: " + (endCoords.pageX-startCoords.pageX) + "x, " + (endCoords.pageY-startCoords.pageY) + "y"); 
});