ipad safari: wyłączyć przewijanie i efekt odbijania?

126

Pracuję nad aplikacją opartą na przeglądarce, obecnie rozwijam i projektuję dla przeglądarki iPad Safari.

Szukam dwóch rzeczy na iPadzie: Jak wyłączyć przewijanie w pionie na stronach, które tego nie wymagają? i jak mogę wyłączyć efekt sprężystego odskoku?

Adam
źródło
odnieś się do następującej odpowiedzi, tylko taka, która działała dla mnie i jest aktualna ( stackoverflow.com/a/51176339/1979180 )
frage

Odpowiedzi:

157

Ta odpowiedź nie ma już zastosowania, chyba że tworzysz oprogramowanie dla bardzo starego urządzenia z systemem iOS ... Zobacz inne rozwiązania


Odpowiedź z 2011 roku: W przypadku aplikacji internetowej / html działającej w iOS Safari potrzebujesz czegoś podobnego

document.ontouchmove = function(event){
    event.preventDefault();
}

W przypadku iOS 5 warto wziąć pod uwagę: document.ontouchmove i przewijanie w iOS 5

Aktualizacja wrzesień 2014: Dokładniejsze podejście można znaleźć tutaj: https://github.com/luster-io/prevent-overscroll . Informacje na ten temat oraz wiele przydatnych porad dotyczących aplikacji internetowych można znaleźć pod adresem http://www.luster.io/blog/9-29-14-mobile-web-checklist.html

Aktualizacja z marca 2016 r .: Ten ostatni link nie jest już aktywny - zobacz https://web.archive.org/web/20151103001838/http://www.luster.io/blog/9-29-14-mobile-web-checklist .html dla wersji zarchiwizowanej. Dzięki @falsarella za wskazanie tego.

Oskar Austegard
źródło
1
Mam aplikację internetową działającą w iOS Safari i próbowałem wyłączyć zdarzenie ontouchmove, ale nadal można zobaczyć efekt odbicia, jeśli zostanie to zrobione ostrożnie. (iOS 5)
Nilesh
7
A co z wyłączeniem efektu odbijania ...?
Yuval A.
6
Problem z tym podejściem polega na tym, że przewijalne elementy div w Twoim domenie nie będą już przewijać. W zależności od konfiguracji domeny można to obejść.
huesforalice
3
Jest tu grupa ludzi, którzy pytają o przewijanie elementów div podczas korzystania z tego, więc ... aby umożliwić przewijanie tych elementów div, dodaj. onTouchMove: function(e) { e.stopPropagation(); e.stopImmediatePropagation(); } Zapobiegnie to uderzaniu zdarzenia w ciało, ale treść nie będzie odbijana. Edycja: Zakładamy, że ustawiłeś $ ('div'). On ('touchmove', ... onTouchMove);
Matt Kenefick
1
@OskarAustegard Ostatni link nie działał dla mnie, ale mogłem znaleźć zawartość w archiwum internetowym: web.archive.org/web/20151103001838/http://www.luster.io/blog/…
falsarella
116

Możesz także zmienić położenie body / html na naprawione:

body,
html {
  position: fixed;
}
Ben Bos
źródło
2
To faktycznie działało bardzo dobrze na iPadzie iOS 8.2 Safari; brak efektu odbijania.
Akseli Palén
3
Najlepszy sposób na zrobienie tego, jaki widziałem do tej pory
hildende
8
Nie działa, jeśli chcesz umieścić coś z pozycją: bezwzględną i wszystkimi bokami ustawionymi na 0 (aby utworzyć pełnoekranowy element div) - cały dokument kurczy się do zera.
riv
4
Strona przeskakuje z powrotem na górę strony, kiedy jej używam, a następnie skupiam się na danych wejściowych. Czy znasz sposób na obejście tego?
Julie
1
@riv dodając szerokość: 100%; wysokość: 100% zarówno body, jak i html pomogły mi.
Tim
58

Aby zapobiec przewijaniu w nowoczesnych przeglądarkach mobilnych, musisz dodać pasywne: false. Wyrywałem sobie włosy, żeby to zadziałało, dopóki nie znalazłem tego rozwiązania. Znalazłem to wspomniane tylko w jednym miejscu w Internecie.

function preventDefault(e){
    e.preventDefault();
}

function disableScroll(){
    document.body.addEventListener('touchmove', preventDefault, { passive: false });
}
function enableScroll(){
    document.body.removeEventListener('touchmove', preventDefault);
}

Christopher Vickers
źródło
7
Bez { passive: false }tego na pewno nie działa !!! Witaj na StackOverflow dude
Ser
2
Dziękuję za to rozwiązanie!
Paul Z.
6
To jest poprawna odpowiedź. Możesz zobaczyć wyjaśnienie tutaj: developer.mozilla.org/en-US/docs/Web/API/EventTarget/ ... po tym, jak touchmove Chrome 54 domyślnie ustawił wartość pasywną na true, co oznacza, że ​​wywołania disableDefault byłyby ignorowane. Dlatego musisz przekazać {passive: false}, aby wywołanie prevDefault nie było ignorowane.
derickito
1
Deklarujesz funkcję w JS - Ale jak wywołać tę funkcję na elemencie, aby działała zgodnie z sugestią?
ikwyl6
4
Działa to świetnie, jeśli chcesz wyłączyć wszystkie rodzaje przewijania. Ale co, jeśli chcę tylko wyłączyć przewijanie treści i zachować możliwość przewijania elementu overflow-y: scroll? Na przykład mając modal z wyższą wysokością widoku niż ciało.
Calsal
7

Możesz użyć tego fragmentu kodu jQuery, aby to zrobić:

$(document).bind(
      'touchmove',
          function(e) {
            e.preventDefault();
          }
);

Spowoduje to zablokowanie przewijania w pionie, a także wszelkich efektów odbijania się na Twoich stronach.

Alessandro Incarnati
źródło
11
To nie jest JavaScript, to jQuery. Powinieneś o tym wspomnieć, nie wszyscy używają tego frameworka.
inta
jak zatrzymać odbijanie lub przewijanie w poziomie
fidel castro
Przewijanie poziome można nawet wyłączyć za pomocą samego css, stosując overflow-x: hidden; do głównego pojemnika. Zauważyłem, że w najnowszych wersjach Safari nie można jednak wyłączyć efektu odbicia. To natywna funkcja przeglądarki na urządzeniach mobilnych.
Alessandro Incarnati
6
@inta Mówiąc, że to w rzeczywistości jest JavaScript. To po prostu nie jest czysty javascript.
Ben Lorantfy
6
overflow: scroll;
-webkit-overflow-scrolling: touch;

Na kontenerze możesz ustawić efekt odbicia wewnątrz elementu

Źródło: http://www.kylejlarson.com/blog/2011/fixed-elements-and-scrolling-divs-in-ios-5/

user956584
źródło
1
Razem z overflow:hiddenon the <body>nadal jest to najlepsze rozwiązanie. Jednak podczas otwierania klawiatury lub przesuwania w dół ekranu, nie będzie już działać.
Fabian von Ellerts
spróbuj wejść onfocus usuń przepełnienie
user956584
4

Wiem, że jest to trochę poza trasą, ale używałem Swiffy do konwersji Flasha na interaktywną grę HTML5 i napotkałem ten sam problem z przewijaniem, ale nie znalazłem rozwiązania, które działało.

Problem, jaki miałem, polegał na tym, że scena Swiffy zajmowała cały ekran, więc po załadowaniu zdarzenie dotknięcia dokumentu nigdy nie zostało wyzwolone.

Jeśli próbowałem dodać to samo zdarzenie do kontenera Swiffy, zostało ono zastąpione zaraz po załadowaniu sceny.

W końcu rozwiązałem to (raczej niechlujnie), stosując zdarzenie touchmove do każdego DIV na scenie. Ponieważ te elementy div również się zmieniały, musiałem je sprawdzać.

To było moje rozwiązanie, które wydaje się działać dobrze. Mam nadzieję, że będzie to pomocne dla każdego, kto próbuje znaleźć to samo rozwiązanie co ja.

var divInterval = setInterval(updateDivs,50);
function updateDivs(){
$("#swiffycontainer > div").bind(
    'touchmove',
     function(e) {
        e.preventDefault();
    }
);}
Tomek
źródło
to wyłącza całe przewijanie w iPadzie
fidel castro
3

Kod do usuwania ipad safari: wyłącz przewijanie i efekt odbijania

   document.addEventListener("touchmove", function (e) {
        e.preventDefault();
    }, { passive: false });

Jeśli masz tag canvas w dokumencie, czasami będzie to miało wpływ na użyteczność obiektu wewnątrz Canvas (przykład: ruch obiektu); więc dodaj poniższy kod, aby to naprawić.

    document.getElementById("canvasId").addEventListener("touchmove", function (e) {
        e.stopPropagation();
    }, { passive: false });
Teju VB
źródło
2

Spróbuj tego rozwiązania JS :

var xStart, yStart = 0; 

document.addEventListener('touchstart', function(e) {
    xStart = e.touches[0].screenX;
    yStart = e.touches[0].screenY;
}); 

document.addEventListener('touchmove', function(e) {
    var xMovement = Math.abs(e.touches[0].screenX - xStart);
    var yMovement = Math.abs(e.touches[0].screenY - yStart);
    if((yMovement * 3) > xMovement) {
        e.preventDefault();
    }
});

Zapobiega domyślnemu przewijaniu i odbijaniu gestów przeglądarki Safari bez odłączania detektorów zdarzeń dotykowych.

Andrii Verbytskyi
źródło
Dzięki temu aplikacja internetowa nie będzie całkowicie przewijała elementu body.
MartijnICU
2

żadne z rozwiązań nie działa dla mnie. Tak to robię.

  html,body {
      position: fixed;
      overflow: hidden;
    }
  .the_element_that_you_want_to_have_scrolling{
      -webkit-overflow-scrolling: touch;
  }
zły kiwi
źródło
Zrobiłbym .the_element_that_you_want_to_have_scrolling {scrolling: touch; }
Roy Segall,
Twoja odpowiedź zadziałała dla mnie w przypadku treści HTML, ale nie mogę przewinąć „the_element_that_you_want_to_have_scrolling”. Ten element jest zagnieżdżony w kilku elementach div znajdujących się pod treścią. Czy ma znaczenie, jakie byłyby typowe znaczniki elementu dla tego zagnieżdżonego elementu div, że chcę, aby był przewijany? Mam pozycję: względną.
ikwyl6
1

Dla tych, którzy używają MyScript aplikacji internetowej i zmagają się z przewijaniem / przeciąganiem ciała (na iPadzie i tabletach) zamiast pisać:

<body touch-action="none" unresolved>

To naprawiło to dla mnie.

Miro
źródło
1

Możesz użyć js, aby zapobiec przewijaniu:

let body = document.body;

let hideScroll = function(e) {
  e.preventDefault();
};

function toggleScroll (bool) {

  if (bool === true) {
    body.addEventListener("touchmove", hideScroll);
  } else {
    body.removeEventListener("touchmove", hideScroll);
  }
}

I niż tylko uruchamianie / zatrzymywanie toggleScrollfunkcji podczas otwierania / zamykania trybu.

Lubię to toggleScroll(true) / toggleScroll(false)

(To jest tylko dla iOS, na Androidzie nie działa)

Vlad Novikov
źródło
1

Wypróbuj to rozwiązanie JS, które przełącza webkitOverflowScrollingstyl. Sztuczka polega na tym, że ten styl jest wyłączony, mobilne Safari przechodzi do zwykłego przewijania i zapobiega nadmiernemu odbiciu - niestety nie jest w stanie anulować trwającego przeciągania. To złożone rozwiązanie śledzi również, onscrollgdy odbicie od góry sprawia, scrollTopże wartość ujemna może być śledzona. To rozwiązanie zostało przetestowane na iOS 12.1.1 i ma jedną wadę: podczas przyspieszania przewijania nadal występuje pojedyncze przeskakiwanie, ponieważ resetowanie stylu może nie anulować go natychmiast.

function preventScrollVerticalBounceEffect(container) {
  setTouchScroll(true) //!: enable before the first scroll attempt

  container.addEventListener("touchstart", onTouchStart)
  container.addEventListener("touchmove", onTouch, { passive: false })
  container.addEventListener("touchend", onTouchEnd)
  container.addEventListener("scroll", onScroll)

  function isTouchScroll() {
    return !!container.style.webkitOverflowScrolling
  }

  let prevScrollTop = 0, prevTouchY, opid = 0

  function setTouchScroll(on) {
    container.style.webkitOverflowScrolling = on ? "touch" : null

    //Hint: auto-enabling after a small pause makes the start
    // smoothly accelerated as required. After the pause the
    // scroll position is settled, and there is no delta to
    // make over-bounce by dragging the finger. But still,
    // accelerated content makes short single over-bounce
    // as acceleration may not be off instantly.

    const xopid = ++opid
    !on && setTimeout(() => (xopid === opid) && setTouchScroll(true), 250)

    if(!on && container.scrollTop < 16)
      container.scrollTop = 0
    prevScrollTop = container.scrollTop
  }

  function isBounceOverTop() {
    const dY = container.scrollTop - prevScrollTop
    return dY < 0 && container.scrollTop < 16
  }

  function isBounceOverBottom(touchY) {
    const dY = touchY - prevTouchY

    //Hint: trying to bounce over the bottom, the finger moves
    // up the screen, thus Y becomes smaller. We prevent this.

    return dY < 0 && container.scrollHeight - 16 <=
      container.scrollTop + container.offsetHeight
  }

  function onTouchStart(e) {
    prevTouchY = e.touches[0].pageY
  }

  function onTouch(e) {
    const touchY = e.touches[0].pageY

    if(isBounceOverBottom(touchY)) {
      if(isTouchScroll())
        setTouchScroll(false)
      e.preventDefault()
    }

    prevTouchY = touchY
  }

  function onTouchEnd() {
    prevTouchY = undefined
  }

  function onScroll() {
    if(isTouchScroll() && isBounceOverTop()) {
      setTouchScroll(false)
    }
  }
}
Anton Baukin
źródło
1

poprawiona odpowiedź @Ben Bos i skomentowana przez @Tim

Ten CSS pomoże uniknąć problemów z przewijaniem i wydajnością przy ponownym renderowaniu CSS, ponieważ pozycja została zmieniona / niewielkie opóźnienie bez szerokości i wysokości

body,
html {
  position: fixed;
  width: 100%; 
  height: 100%
}

auronsan zenx
źródło
Na IOS13 jest to dla mnie najczystsze rozwiązanie i nie znalazłem jeszcze żadnych wad ...
Soylent Graham
0

Dla tych z Was, którzy nie chcą pozbyć się odbijania, ale chcą tylko wiedzieć, kiedy się zatrzymają (na przykład, aby rozpocząć obliczenia odległości ekranu), mogą wykonać następujące czynności (kontener to przepełniony element kontenera):

    const isBouncing = this.container.scrollTop < 0 ||
    this.container.scrollTop + this.container.offsetHeight >
        this.container.scrollHeight
Phil
źródło
0

Wyłącz efekt przewijania odbijania safari:

html,
body {
  height: 100%;
  width: 100%;
  overflow: auto;
  position: fixed;
}  
Abolfazl Baghshahi
źródło
-1

Podobnie jak w przypadku złego kiwi, sprawiłem, że działa na podstawie wysokości, a nie pozycji:

html,body {
  height: 100%;
  overflow: hidden;
}

.the_element_that_you_want_to_have_scrolling{
  -webkit-overflow-scrolling: touch;
}
austinh7
źródło
jako dokument umożliwi to odbicie również po nie wyłączeniu pędu
CaSUaL
@CaSUaL Nie wiesz, co masz na myśli? To rozwiązanie zadziałało w moim przypadku użycia ...
austinh7
-1

Rozwiązanie przetestowane, działa na iOS 12.x.

Oto problem, który napotkałem:

<body> <!-- the whole body can be scroll vertically -->
  <article>

    <my_gallery> <!-- some picture gallery, can be scroll horizontally -->
    </my_gallery>

  </article>
</body>

Kiedy przewijam galerię, ciało zawsze przewija się (ruchy człowieka nie są tak naprawdę poziome), przez co moja galeria jest bezużyteczna.

Oto, co zrobiłem, gdy moja galeria zaczęła się przewijać

var html=jQuery('html');
html.css('overflow-y', 'hidden');
//above code works on mobile Chrome/Edge/Firefox
document.ontouchmove=function(e){e.preventDefault();} //Add this only for mobile Safari

A kiedy moja galeria zakończy przewijanie ...

var html=jQuery('html');
html.css('overflow-y', 'scroll');
document.ontouchmove=function(e){return true;}

Mam nadzieję, że to pomoże ~

RRTW
źródło