2013-03-09 23 views
9

Załóżmy, że chcemy, aby aplikacja internetowa wyglądała jak natywna aplikacja z "Dodaj do ekranu głównego". Jednym z pierwszych kroków jest wyłączenie domyślnego przewijania. Łatwo, prawda?Przewijanie strony w iOS: przewijanie z przepełnieniem: dotknij

// window or document 
window.addEventListener("touchmove", function(event) { 
    // no more scrolling 
    event.preventDefault(); 
}, false); 

To wszystko cacy, aż dodasz overflow-scrolling do mieszanki. Mówiąc dokładniej, na iOS byłby to -webkit-overflow-scrolling: touch.

/* #scrollable happens to be a ul */ 
#scrollable { 
    overflow-y: auto; 
    -webkit-overflow-scrolling: touch; 
} 

Dzięki dodaniu funkcji zapobiegania zdarzeniom, przyspieszane sprzętowo przewijanie w kontenerze nie działa, wyraźnie nie jest to zamierzony efekt.

Oczywistym rozwiązaniem wygląda mniej więcej tak:

// you could do this for multiple elements, of course 
var scrollable = document.querySelector("#scrollable"); 
scrollable.addEventListener("touchmove", function(event) { 
    // no more bubbling :) 
    event.stopPropagation(); 
}, false); 

To rozwiązanie wprowadza problemu, jeśli jednak spróbować przewiń w lewo lub w prawo w #scrollable, to powraca do słuchacza domyślnego przewijania. Oczywiście, należy monitorować zdarzenia, aby sprawdzić, czy zdarzenie touchmove śledzi w lewo lub w prawo, prawda? Niestety, nie, ponieważ również w okolicznościach, których nie rozumiem, powróć do domyślnego odbiornika przewijania, przewijając pionowo w kontenerze.

Co teraz? Co gorsza, chcemy być idealnie w stanie obsłużyć click lub kliknij podobnego wydarzenia na poszczególnych li s (czytaj: touchstart):

var items = scrollable.querySelectorAll("#scrollable li"); 
for (var item = 0; item < items.length; item++) { 
    items[item].addEventListener("touchstart", function() { 
     // handle the touch start 
    }, false); 
} 

Aby rozwiązać ten problem, możemy zwrócić się po prostu za pomocą click zdarzenia, ale domyślnie celem jest sprawienie, by webapp "czuł się" natywny ze względu na opóźnienie między dotknięciem a odpowiedzią. Aby rozwiązać ten problem, dodamy detektor zdarzeń dla touchstart i touchend:

var items = scrollable.querySelectorAll("#scrollable li"); 
var activeItem = null, startTouch = null; 
for (var item = 0; item < items.length; item++) { 
    items[item].addEventListener("touchstart", function(event) { 
     startTouch = event.touches[0]; 
     activeItem = this; 
    }, false); 
    items[item].addEventListener("touchend", function(event) { 
     var touch = event.changedTouches[0]; 
     var deltaX = touch.pageX - startTouch.pageX 
     var deltaY = touch.pageY - startTouch.pageY; 
     // require the touchstart to be within 10 pixels of the touchend 
     if (deltaX * deltaX + deltaY * deltaY <= 100) 
      // handle "click" event 
    }, false); 
} 

To wszystko dobrze i dobre, ale wciąż nie rozwiązany problem z domyślna strona przewijanie przejęcie kontroli niektórych touchmove wydarzeń. Jakieś pomysły?

Odpowiedz

8

Spróbuj swapping wokół logiki w swoich słuchaczy elementów window i scrollable tak:

// window or document 
window.addEventListener("touchmove", function(event) { 
    if (!event.target.classList.contains('scrollable')) { 
    // no more scrolling 
    event.preventDefault(); 
    } 
}, false); 

// No special listeners needed on .scrollable elements 

W ten sposób można zapobiec jedynie domyślne podczas próby przewijać elementy nie przewijane.

Nadal będzie występować problem polegający na tym, że przewijanie u góry/u dołu przewijanej zawartości może spowodować "odbicie" całej aplikacji. Aby rozwiązać ten problem, zobacz Joe Lambert's ScrollFix.

Powiązane problemy