ipad safari: desativar a rolagem e o efeito de rejeição?

126

Eu estou trabalhando em um aplicativo baseado em navegador, atualmente estou desenvolvendo e estilizando o navegador ipad safari.

Estou procurando duas coisas no ipad: Como posso desativar a rolagem vertical para páginas que não exigem isso? e como posso desativar o efeito de ressalto elástico?

Adão
fonte
consulte a resposta a seguir apenas uma que funcionou para mim e é atual ( stackoverflow.com/a/51176339/1979180 )
frage 10/01/19

Respostas:

157

Esta resposta não é mais aplicável, a menos que você esteja desenvolvendo para um dispositivo iOS muito antigo ... Consulte outras soluções


Resposta de 2011: para um aplicativo web / html em execução no iOS Safari, você deseja algo como

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

Para o iOS 5, convém levar o seguinte em consideração: document.ontouchmove e rolagem no iOS 5

Atualização em setembro de 2014: Uma abordagem mais completa pode ser encontrada aqui: https://github.com/luster-io/prevent-overscroll . Para isso e muitos conselhos úteis sobre aplicativos da web, consulte http://www.luster.io/blog/9-29-14-mobile-web-checklist.html

Atualização em março de 2016: esse último link não está mais ativo - consulte https://web.archive.org/web/20151103001838/http://www.luster.io/blog/9-29-14-mobile-web-checklist .html para a versão arquivada. Obrigado @falsarella por apontar isso.

Oskar Austegard
fonte
1
Eu tenho o webapp em execução no iOS Safari e tentei desativar o evento ontouchmove, mas ainda é possível ver o efeito de rejeição se feito com cuidado. (iOS 5)
Nilesh
7
Que tal desabilitar o efeito de rejeição ...?
Yuval A.
6
O problema com essa abordagem é que os divs roláveis ​​no seu Dom não rolam mais. Dependendo da configuração do seu dom, existem maneiras de contornar isso.
precisa saber é o seguinte
3
Há um monte de gente aqui perguntando sobre a rolagem de divs enquanto usa isso para .. para torná-los roláveis, adicione onTouchMove: function(e) { e.stopPropagation(); e.stopImmediatePropagation(); } Isso impedirá que o evento atinja o corpo, mas o corpo permanecerá não-saltitante. Edit: Isso pressupõe que você defina $ ('div'). On ('touchmove', ... onTouchMove);
precisa saber é o seguinte
1
@OskarAustegard O último link não funcionou para mim, mas eu pude encontrar o conteúdo no arquivo da web: web.archive.org/web/20151103001838/http://www.luster.io/blog/…
falsarella
116

Você também pode alterar a posição do corpo / html para fixo:

body,
html {
  position: fixed;
}
Ben Bos
fonte
2
Isso realmente funcionou muito bem no iPad iOS 8.2 Safari; nenhum efeito de rejeição mais.
Akseli Palén
3
Melhor maneira de fazer isso eu tenho visto até agora
hildende
8
Não funciona se você deseja colocar algo com a posição: absoluto e todos os lados definidos como 0 (para fazer uma div em tela cheia) - todo o documento diminui para nada.
riv
4
A página volta para o topo da página para mim quando eu uso isso e depois me concentro em uma entrada. Você conhece uma maneira de contornar isso?
Julie
1
@riv adicionando largura: 100%; height: 100% para corpo e html me ajudaram.
Tim
57

Para impedir a rolagem em navegadores móveis modernos, você deve adicionar o passivo: false. Eu estava puxando meu cabelo para fazer isso funcionar até encontrar essa solução. Eu só encontrei isso mencionado em outro lugar na internet.

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

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

Christopher Vickers
fonte
7
Sem { passive: false }ele definitivamente não está funcionando !!! Bem-vindo ao StackOverflow cara
Ser
2
Agradeço por fornecer esta solução!
Paul Z.
6
Essa é a resposta correta. Você pode ver a explicação aqui: developer.mozilla.org/en-US/docs/Web/API/EventTarget/… depois que o Chrome 54 touchmove assumiu o padrão passivo para true, o que significa que as chamadas preventDefault seriam ignoradas. É por isso que você deve passar {passive: false}, para que a chamada preventDefault não seja ignorada.
Derickito 7/06
1
Você está declarando a função em JS - Mas como você chama essa função em um elemento para que funcione como sugerido?
precisa saber é o seguinte
4
Isso funciona muito bem se você deseja desativar todos os tipos de rolagem. Mas e se eu quiser apenas desativar a rolagem no corpo e manter a possibilidade de rolar em um elemento overflow-y: scroll? Por exemplo, ter um modal com uma altura de vista mais alta que o corpo.
Calsal 9/10/19
7

Você pode usar este trecho de código jQuery para fazer isso:

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

Isso bloqueará a rolagem vertical e também qualquer efeito de retorno nas suas páginas.

Alessandro Incarnati
fonte
11
Isso não é Javascript, é jQuery. Você deve mencionar que nem todo mundo está usando essa estrutura.
inta
Como posso parar salto horizontal ou rolagem
fidel castro
Rolagem horizontal, você pode até desativá-lo com apenas css, aplicando overflow-x: hidden; para o seu recipiente principal. Notei nas versões mais recentes do safari que você não pode desativar o efeito de rejeição. É um recurso nativo do navegador em dispositivos móveis.
Alessandro Incarnati
6
@inta Apenas dizendo que isso é javascript. Não é apenas javascript puro.
Ben Lorantfy
6
overflow: scroll;
-webkit-overflow-scrolling: touch;

No contêiner, você pode definir o efeito de rejeição dentro do elemento

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

user956584
fonte
1
Juntamente com overflow:hiddeno <body>, essa ainda é a melhor solução. No entanto, ao abrir o teclado ou deslizar pela parte inferior da tela, ele não funcionará mais.
Fabian von Ellerts
tente entrada onfocus remover estouro
user956584
4

Sei que isso está um pouco fora de pista, mas tenho usado o Swiffy para converter o Flash em um jogo interativo em HTML5 e me deparei com o mesmo problema de rolagem, mas não encontrei soluções que funcionassem.

O problema que tive foi que o estágio Swiffy estava ocupando a tela inteira; assim, assim que foi carregado, o evento touchmove do documento nunca foi acionado.

Se eu tentasse adicionar o mesmo evento ao contêiner Swiffy, ele seria substituído assim que o palco fosse carregado.

No final, eu o resolvi (de maneira bastante confusa) aplicando o evento touchmove a cada DIV dentro do palco. Como esses divs também estavam em constante mudança, eu precisava continuar verificando-os.

Esta foi a minha solução, que parece funcionar bem. Espero que seja útil para qualquer pessoa que tente encontrar a mesma solução que eu.

var divInterval = setInterval(updateDivs,50);
function updateDivs(){
$("#swiffycontainer > div").bind(
    'touchmove',
     function(e) {
        e.preventDefault();
    }
);}
Tom
fonte
isso desativa toda rolagem no ipad
fidel castro
3

Código para remover o ipad safari: desative a rolagem e o efeito de rejeição

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

Se você tiver uma marca de tela dentro do documento, em algum momento isso afetará a usabilidade do objeto dentro do Canvas (exemplo: movimento do objeto); adicione o código abaixo para corrigi-lo.

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

Tente esta solução 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();
    }
});

Impede a rolagem padrão do Safari e gestos de rejeição sem desconectar os ouvintes de eventos de toque.

Andrii Verbytskyi
fonte
Isso impede que o aplicativo da web role completamente no elemento body.
MartijnICU
2

nenhuma das soluções funciona para mim. É assim que eu faço.

  html,body {
      position: fixed;
      overflow: hidden;
    }
  .the_element_that_you_want_to_have_scrolling{
      -webkit-overflow-scrolling: touch;
  }
kiwi com raiva
fonte
Eu faria o. }
Roy Segall
Sua resposta funcionou para mim no html, body, mas não consigo "the_element_that_you_want_to_have_scrolling" para rolar. Esse elemento está aninhado dentro de algumas divs que estão sob o corpo. Importa o que qualquer uma das tags de elemento típico seria para esta div aninhada que eu quero que ela role? Eu tenho posição: relativo.
ikwyl6 21/02
1

Para aqueles que usam o MyScript, o Web App, e estão lutando com o corpo rolando / arrastando (no iPad e no Tablets), em vez de realmente escrever:

<body touch-action="none" unresolved>

Isso consertou para mim.

Miro
fonte
1

Você pode usar js para impedir a rolagem:

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 do que apenas executar / parar a toggleScrollfunção quando você abre / fecha o modal.

Como isso toggleScroll(true) / toggleScroll(false)

(Isso é apenas para iOS, no Android não está funcionando)

Vlad Novikov
fonte
1

Experimente esta solução JS que alterna o webkitOverflowScrollingestilo. O truque aqui é que esse estilo está desativado, o Safari móvel vai para a rolagem comum e evita o excesso de salto - infelizmente, não é possível cancelar o arrasto em andamento. Essa solução complexa também rastreia, onscrollpois o salto por cima torna scrollTopnegativos que podem ser rastreados. Esta solução foi testada no iOS 12.1.1 e tem uma única desvantagem: enquanto a aceleração do deslocamento único de rolagem ainda acontece, a redefinição do estilo pode não ser cancelada imediatamente.

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
fonte
1

resposta melhorada @Ben Bos e comentado por @Tim

Esse css ajudará a evitar problemas de rolagem e desempenho com a re-renderização do css, pois a posição foi alterada / pouco atrasada sem largura e altura

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

auronsan zenx
fonte
Em IOS13, esta é a solução mais limpa para mim, e ainda não encontrou quaisquer inconvenientes ...
Soylent Graham
0

Para aqueles que não querem se livrar da rejeição, mas apenas para saber quando ela pára (por exemplo, para iniciar um cálculo das distâncias da tela), você pode fazer o seguinte (container é o elemento de container transbordando):

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

Desative o efeito de rolagem de retorno do safari:

html,
body {
  height: 100%;
  width: 100%;
  overflow: auto;
  position: fixed;
}  
Abolfazl Baghshahi
fonte
-1

Semelhante ao kiwi zangado, consegui fazê-lo usando a altura em vez da posição:

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

.the_element_that_you_want_to_have_scrolling{
  -webkit-overflow-scrolling: touch;
}
austinh7
fonte
como o doc isso vai permitir o salto também depois impulso não disable
Casual
@CaSUaL Não sabe o que quer dizer? Esta solução funcionou para o meu caso de uso ...
austinh7
-1

Solução testada, funciona no iOS 12.x

Este é um problema que eu estava encontrando:

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

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

  </article>
</body>

Enquanto eu rolar minha galeria, o corpo sempre se desloca (o furto humano não é realmente horizontal), o que torna minha galeria inútil.

Aqui está o que eu fiz enquanto minha galeria começou a rolar

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 minha galeria terminar sua rolagem ...

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

Espero que isso ajude ~

RRTW
fonte