2013-02-26 26 views
36

Mam wniosek złożony w AngularJS, który ma klawisze strzałek do przełączania widoków.Jak zaimplementować gesty przesuwania na urządzenia mobilne?

Chcę zaimplementować tę nawigację za pomocą przeciągnięcia dla urządzeń dotykowych. Próbowałem biblioteki jGestures, ale nie idzie dobrze z machnięcia. Polecono mi NIE używać jquery mobile.

Czy istnieje inny sposób realizacji machnięcia?

EDYTOWANIE: Nie wykrywa przesunięcia w sposób czysty. Testowałem go na wielu urządzeniach, w tym iPad i zajmuje wiele swipes zrobić akcję (routing w moim przypadku).

+0

Możesz zajrzeć do problemów, które pojawiły się w jGestures. Sam tego nie użyłem, ale wygląda na to, że napisałem świetną wersję niestandardowego kodu, który napisałem dla prostej obsługi gestów (i gdzie indziej). –

+0

Dodano je do edycji. – fotuzlab

+0

"Polecono mi NIE używać jquery mobile." czemu? – givanse

Odpowiedz

23

Czy próbowałeś Hammerjs? Obsługuje gesty przesunięcia za pomocą prędkości dotyku. http://eightmedia.github.com/hammer.js/

+0

Użyłem http://quojs.tapquo.com/. To działało dobrze. Słyszałem wiele pozytywów o HammerJS, spróbuję tego w innym projekcie. Dzięki za twoją odpowiedź. – fotuzlab

+0

Napisałem prostą usługę pakowania Hammerjs. Działa wspaniale z Angular. –

+0

Dzięki za rekomendację! hammerjs działa z bieżącą wersją JQuery bez konieczności migrowania jquery.mobile. Brak ostrzeżeń, brak błędów. MIŁY! –

33

Zrobiłem tę funkcję dla moich potrzeb.

Zapraszam do korzystania z niego. Działa świetnie na urządzeniach mobilnych.

function detectswipe(el,func) { 
    swipe_det = new Object(); 
    swipe_det.sX = 0; swipe_det.sY = 0; swipe_det.eX = 0; swipe_det.eY = 0; 
    var min_x = 30; //min x swipe for horizontal swipe 
    var max_x = 30; //max x difference for vertical swipe 
    var min_y = 50; //min y swipe for vertical swipe 
    var max_y = 60; //max y difference for horizontal swipe 
    var direc = ""; 
    ele = document.getElementById(el); 
    ele.addEventListener('touchstart',function(e){ 
    var t = e.touches[0]; 
    swipe_det.sX = t.screenX; 
    swipe_det.sY = t.screenY; 
    },false); 
    ele.addEventListener('touchmove',function(e){ 
    e.preventDefault(); 
    var t = e.touches[0]; 
    swipe_det.eX = t.screenX; 
    swipe_det.eY = t.screenY;  
    },false); 
    ele.addEventListener('touchend',function(e){ 
    //horizontal detection 
    if ((((swipe_det.eX - min_x > swipe_det.sX) || (swipe_det.eX + min_x < swipe_det.sX)) && ((swipe_det.eY < swipe_det.sY + max_y) && (swipe_det.sY > swipe_det.eY - max_y) && (swipe_det.eX > 0)))) { 
     if(swipe_det.eX > swipe_det.sX) direc = "r"; 
     else direc = "l"; 
    } 
    //vertical detection 
    else if ((((swipe_det.eY - min_y > swipe_det.sY) || (swipe_det.eY + min_y < swipe_det.sY)) && ((swipe_det.eX < swipe_det.sX + max_x) && (swipe_det.sX > swipe_det.eX - max_x) && (swipe_det.eY > 0)))) { 
     if(swipe_det.eY > swipe_det.sY) direc = "d"; 
     else direc = "u"; 
    } 

    if (direc != "") { 
     if(typeof func == 'function') func(el,direc); 
    } 
    direc = ""; 
    swipe_det.sX = 0; swipe_det.sY = 0; swipe_det.eX = 0; swipe_det.eY = 0; 
    },false); 
} 

function myfunction(el,d) { 
    alert("you swiped on element with id '"+el+"' to "+d+" direction"); 
} 

Aby wykorzystać funkcję tylko stosować jak

detectswipe('an_element_id',myfunction); 

detectswipe('an_other_element_id',my_other_function); 

Jeżeli bezstykowa wykrycia funkcję "myfunction" nazywana jest parametrem element identyfikatora oraz "L, R, U, D" (lewo prawo góra dół).

Przykład: http://jsfiddle.net/rvuayqeo/1/

+0

Dziękuję. Zalecam dynamiczne ustawienie 'min_x':' min_x = Math.abs (swipe_det.eY - swipe_det.sY) '. Analog dla innego kierunku. Ponieważ po przesunięciu 400px w górę i tylko 40px w prawo, prawdopodobnie zamierzasz przesunąć w górę. Jednak Twój kod rozpozna prawy ruch. – Sadik

+1

@EscapeNetscape Podoba mi się twoje rozwiązanie do wykrywania przesunięcia. Ale nieprawidłowo identyfikuje pojedyncze i podwójne dotknięcia jako przeciągnięcia. Jak mam to naprawić? – theJollySin

3

Najprostszym rozwiązaniem Odkryłam, że nie wymaga wtyczki jest givanse's answer z podobnym pytaniem:

document.addEventListener('touchstart', handleTouchStart, false);   
document.addEventListener('touchmove', handleTouchMove, false); 

var xDown = null;               
var yDown = null;               

function handleTouchStart(evt) {           
    xDown = evt.touches[0].clientX;          
    yDown = evt.touches[0].clientY;          
}; 



function handleTouchMove(evt) { 
    if (! xDown || ! yDown) { 
     return; 
    } 

var xUp = evt.touches[0].clientX;          
var yUp = evt.touches[0].clientY; 

var xDiff = xDown - xUp; 
var yDiff = yDown - yUp; 

if (Math.abs(xDiff) > Math.abs(yDiff)) {/*most significant*/ 
    if (xDiff > 0) { 
     /* left swipe */ 
    } else { 
     /* right swipe */ 
    }      
} else { 
    if (yDiff > 0) { 
     /* up swipe */ 
    } else { 
     /* down swipe */ 
    }                 
} 
/* reset values */ 
xDown = null; 
yDown = null;            
}; 
1

Hammer time!

Użyłem Hammer JS i pracować z gestem. Przeczytaj szczegóły tutaj: https://hammerjs.github.io/

Dobrze, że to waga znacznie więcej światła, a następnie szybko jQuery mobile. Możesz przetestować go również na swojej stronie internetowej.

0

Podoba mi się twoje rozwiązanie i zaimplementowałem je na mojej stronie - jednak z niewielkimi ulepszeniami.Po prostu chciałem podzielić się moją kod:

function detectSwipe(id, f) { 
    var detect = { 
     startX: 0, 
     startY: 0, 
     endX: 0, 
     endY: 0, 
     minX: 30, // min X swipe for horizontal swipe 
     maxX: 30, // max X difference for vertical swipe 
     minY: 50, // min Y swipe for vertial swipe 
     maxY: 60 // max Y difference for horizontal swipe 
    }, 
     direction = null, 
     element = document.getElementById(id); 

    element.addEventListener('touchstart', function (event) { 
     var touch = event.touches[0]; 
     detect.startX = touch.screenX; 
     detect.startY = touch.screenY; 
    }); 

    element.addEventListener('touchmove', function (event) { 
     event.preventDefault(); 
     var touch = event.touches[0]; 
     detect.endX = touch.screenX; 
     detect.endY = touch.screenY; 
    }); 

    element.addEventListener('touchend', function (event) { 
     if (
      // Horizontal move. 
      (Math.abs(detect.endX - detect.startX) > detect.minX) 
       && (Math.abs(detect.endY - detect.startY) < detect.maxY) 
     ) { 
      direction = (detect.endX > detect.startX) ? 'right' : 'left'; 
     } else if (
      // Vertical move. 
      (Math.abs(detect.endY - detect.startY) > detect.minY) 
       && (Math.abs(detect.endX - detect.startX) < detect.maxX) 
     ) { 
      direction = (detect.endY > detect.startY) ? 'down' : 'up'; 
     } 

     if ((direction !== '') && (typeof f === 'function')) { 
      f(element, direction); 
     } 
    }); 
} 

używać go jak:

detectSwipe('an_element_id', myfunction); 

Albo

detectSwipe('another_element_id', my_other_function); 

Jeśli machnięcia wykryciu funkcję myfunction jest wywoływana z parametrem element id i 'left' , 'right', 'up' lub oder 'down'.