ipad safari: disabilitare lo scorrimento e l'effetto rimbalzo?


126

Sto lavorando su un'app basata su browser, attualmente sto sviluppando e disegnando per il browser Safari per iPad.

Sto cercando due cose sull'ipad: come posso disabilitare lo scorrimento verticale per le pagine che non lo richiedono? e come posso disabilitare l'effetto rimbalzo elastico?


consultare la seguente risposta unica che ha funzionato per me ed è corrente ( stackoverflow.com/a/51176339/1979180 )
Frage

Risposte:


157

Questa risposta non è più applicabile, a meno che tu non stia sviluppando per un dispositivo iOS molto vecchio ... Vedi altre soluzioni


Risposta del 2011: per un'app web / html in esecuzione all'interno di Safari iOS, vuoi qualcosa di simile

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

Per iOS 5 potresti prendere in considerazione quanto segue: document.ontouchmove e scorrimento su iOS 5

Aggiornamento settembre 2014: un approccio più completo può essere trovato qui: https://github.com/luster-io/prevent-overscroll . Per questo e per molti utili consigli sulle webapp, vedere http://www.luster.io/blog/9-29-14-mobile-web-checklist.html

Aggiornamento marzo 2016: l'ultimo collegamento non è più attivo - vedere https://web.archive.org/web/20151103001838/http://www.luster.io/blog/9-29-14-mobile-web-checklist .html per la versione archiviata invece. Grazie @falsarella per averlo fatto notare.


1
Ho una webapp in esecuzione all'interno di iOS Safari e ho provato a disabilitare l'evento ontouchmove ma è ancora possibile vedere l'effetto di rimbalzo se fatto con attenzione. (iOS 5)
Nilesh

7
Che ne dici di disabilitare l'effetto rimbalzo ...?
Yuval A.

6
Il problema con questo approccio è che i div scorrevoli nel tuo dom non scorreranno più. A seconda della configurazione del dom, ci sono modi per aggirare questo problema.
huesforalice

3
Ci sono un sacco di persone qui che chiedono informazioni sullo scorrimento dei div mentre lo usano, quindi ... per rendere quei div scorrevoli, aggiungi onTouchMove: function(e) { e.stopPropagation(); e.stopImmediatePropagation(); } Impedirà che l'evento colpisca il corpo, ma il corpo rimarrà non rimbalzante. Modifica: questo presuppone che tu imposti $ ('div'). On ('touchmove', ... onTouchMove);
Matt Kenefick

1
@OskarAustegard L'ultimo link non ha funzionato per me, ma ho trovato il contenuto nell'archivio web: web.archive.org/web/20151103001838/http://www.luster.io/blog/…
falsarella

116

Puoi anche modificare la posizione del corpo / html in fixed:

body,
html {
  position: fixed;
}

2
In realtà ha funzionato molto bene su iPad iOS 8.2 Safari; nessun effetto di rimbalzo più.
Akseli Palén

3
Il modo migliore per farlo che ho visto finora
hildende

8
Non funziona se vuoi posizionare qualcosa con posizione: assoluto e tutti i lati impostati su 0 (per creare un div a schermo intero) - l'intero documento si riduce a nulla.
riv

4
La pagina torna all'inizio della pagina quando lo uso e poi mi concentro su un input. Conosci un modo per aggirare questo?
Julie

1
@riv aggiunta di larghezza: 100%; altezza: 100% sia per il corpo che per l'html mi ha aiutato.
Tim

58

Per impedire lo scorrimento sui browser mobili moderni è necessario aggiungere il passivo: false. Mi stavo strappando i capelli per farlo funzionare finché non ho trovato questa soluzione. Ho trovato questo menzionato solo in un altro posto su Internet.

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

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


7
Senza { passive: false }sicuramente non funziona !!! Benvenuto su StackOverflow amico
Ser

2
Ti apprezzo per aver fornito questa soluzione!
Paul Z.29

6
Questa è la risposta corretta. Puoi vedere la spiegazione qui: developer.mozilla.org/en-US/docs/Web/API/EventTarget/… dopo che Chrome 54 touchmove ha impostato come predefinito passivo true, il che significa che le chiamate preventDefault verrebbero ignorate. Ecco perché devi passare {passive: false}, quindi la chiamata preventDefault non viene ignorata.
derickito

1
Stai dichiarando la funzione in JS - Ma come chiami questa funzione su un elemento in modo che funzioni come suggerito?
ikwyl6

4
Funziona benissimo se vuoi disabilitare tutti i tipi di scorrimento. Ma cosa succede se voglio solo disabilitare lo scorrimento sul corpo e mantenere la possibilità di scorrere su un elemento con overflow-y: scroll? Ad esempio, avere un modale con un'altezza di visualizzazione più alta del corpo.
Calsal

7

Puoi utilizzare questo frammento di codice jQuery per fare ciò:

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

Ciò bloccherà lo scorrimento verticale e anche qualsiasi effetto di rimbalzo che si verifica sulle tue pagine.


11
Questo non è Javascript, è jQuery. Dovresti menzionarlo, non tutti usano quel framework.
inta

come posso interrompere il rimbalzo o lo scorrimento orizzontale
fidel castro

Scorrimento orizzontale potresti anche disabilitarlo con solo css, applicando overflow-x: hidden; al tuo contenitore principale. Ho notato che nelle ultime versioni di safari non è possibile disabilitare l'effetto rimbalzo. È una funzionalità nativa del browser sui dispositivi mobili.
Alessandro Incarnati

6
@inta Solo dicendo questo in realtà è javascript. Non è solo javascript puro.
Ben Lorantfy

6
overflow: scroll;
-webkit-overflow-scrolling: touch;

Sul contenitore è possibile impostare l'effetto di rimbalzo all'interno dell'elemento

Fonte: http://www.kylejlarson.com/blog/2011/fixed-elements-and-scrolling-divs-in-ios-5/


1
Insieme a overflow:hiddenon the <body>, questa è ancora la soluzione migliore. Tuttavia, quando si apre la tastiera o si scorre nella parte inferiore dello schermo, non funzionerà più.
Fabian von Ellerts,

prova input onfocus rimuovi overflow
user956584

4

So che questo è leggermente fuori pista, ma ho utilizzato Swiffy per convertire Flash in un gioco HTML5 interattivo e ho riscontrato lo stesso problema di scorrimento ma non ho trovato soluzioni che funzionassero.

Il problema che ho avuto è stato che lo stadio Swiffy occupava l'intero schermo, quindi non appena è stato caricato, l'evento touchmove del documento non è mai stato attivato.

Se ho provato ad aggiungere lo stesso evento al contenitore Swiffy, è stato sostituito non appena lo stage è stato caricato.

Alla fine l'ho risolto (piuttosto in modo disordinato) applicando l'evento touchmove a ogni DIV all'interno dello stage. Poiché anche questi div erano in continua evoluzione, dovevo continuare a controllarli.

Questa era la mia soluzione, che sembra funzionare bene. Spero sia utile per chiunque altro cerchi di trovare la mia stessa soluzione.

var divInterval = setInterval(updateDivs,50);
function updateDivs(){
$("#swiffycontainer > div").bind(
    'touchmove',
     function(e) {
        e.preventDefault();
    }
);}

questo disabilita l'intero rotolo in ipad
fidel castro

3

Codice per Per rimuovere iPad Safari: disabilitare lo scorrimento e l'effetto rimbalzo

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

Se hai un tag canvas all'interno del documento, a volte influenzerà l'usabilità dell'oggetto all'interno di Canvas (esempio: movimento dell'oggetto); quindi aggiungi il codice sottostante per risolverlo.

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

2

Prova questa soluzione 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();
    }
});

Impedisce i gesti di scorrimento e di rimbalzo predefiniti di Safari senza scollegare gli ascoltatori di eventi touch.


Ciò impedisce all'app Web di scorrere completamente sull'elemento del corpo.
MartijnICU

2

nessuna delle soluzioni funziona per me. Ecco come lo faccio.

  html,body {
      position: fixed;
      overflow: hidden;
    }
  .the_element_that_you_want_to_have_scrolling{
      -webkit-overflow-scrolling: touch;
  }

Io farei .the_element_that_you_want_to_have_scrolling {scrolling: touch; }
Roy Segall

La tua risposta ha funzionato per me per l'html, body ma non riesco a far scorrere "the_element_that_you_want_to_have_scrolling". Questo elemento è annidato all'interno di alcuni div che si trovano sotto il corpo. Ha importanza quale sarebbe uno qualsiasi dei tag elemento tipici per questo div annidato che voglio che scorra? Ho posizione: relativa.
ikwyl6


1

Per coloro che utilizzano MyScript la Web App e stanno lottando con lo scorrimento / trascinamento del corpo (su iPad e tablet) invece di scrivere effettivamente:

<body touch-action="none" unresolved>

Questo ha risolto il problema per me.


1

Puoi usare js per impedire lo scorrimento:

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);
  }
}

E non solo corri / fermati toggleScroll func quando apri / chiudi modale.

Come questo toggleScroll(true) / toggleScroll(false)

(Questo è solo per iOS, su Android non funziona)


1

Prova questa soluzione JS che alterna lo webkitOverflowScrollingstile. Il trucco qui è che questo stile è disattivato, Safari mobile passa allo scorrimento normale e previene il rimbalzo eccessivo - purtroppo, non è in grado di annullare il trascinamento in corso. Questa soluzione complessa tiene traccia anche in onscrollquanto il rimbalzo sopra le righe rende scrollTopnegativo che può essere tracciato. Questa soluzione è stata testata su iOS 12.1.1 e presenta un unico inconveniente: mentre si accelera lo scorrimento, si verifica ancora un singolo over-bounce poiché il ripristino dello stile potrebbe non annullarlo immediatamente.

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)
    }
  }
}

1

risposta migliorata @Ben Bos e commentata da @Tim

Questo CSS aiuterà a prevenire lo scorrimento e problemi di prestazioni con il ri-rendering CSS perché la posizione è cambiata / poco ritardo senza larghezza e altezza

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


Su IOS13, questa è la soluzione più pulita per me, e non ho ancora trovato alcun inconveniente ...
Soylent Graham

0

Per quelli di voi che non vogliono sbarazzarsi del rimbalzo ma solo per sapere quando si ferma (ad esempio per iniziare un calcolo delle distanze dello schermo), è possibile fare quanto segue (il contenitore è l'elemento contenitore che trabocca):

    const isBouncing = this.container.scrollTop < 0 ||
    this.container.scrollTop + this.container.offsetHeight >
        this.container.scrollHeight

0

Disabilita l'effetto di scorrimento del rimbalzo di Safari:

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

-1

Simile al kiwi arrabbiato, l'ho fatto funzionare usando l'altezza piuttosto che la posizione:

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

.the_element_that_you_want_to_have_scrolling{
  -webkit-overflow-scrolling: touch;
}

come il documento questo abiliterà il rimbalzo anche dopo che lo slancio non sarà disabilitato
CaSUaL

@CaSUaL Non sei sicuro di cosa intendi? Questa soluzione ha funzionato per il mio caso d'uso ...
austinh7

-1

Soluzione testata, funziona su iOS 12.x

Questo è il problema che stavo riscontrando:

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

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

  </article>
</body>

Mentre scorro la mia galleria, il corpo scorre sempre da solo (lo swipe umano non è realmente orizzontale), il che rende la mia galleria inutile.

Ecco cosa ho fatto mentre la mia galleria iniziava a scorrere

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

E quando la mia galleria finisce il suo scorrimento ...

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

Spero che questo aiuti ~

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.