ipad safari: отключить прокрутку и эффект отскока?

126

Я работаю над приложением на основе браузера, в настоящее время я занимаюсь разработкой и стилем для браузера ipad safari.

Я ищу на ipad две вещи: как отключить вертикальную прокрутку для страниц, которые в ней не нуждаются? и как отключить эффект упругого отскока?

Адам
источник
обратитесь к следующему ответу, который работал у меня и является текущим ( stackoverflow.com/a/51176339/1979180 )
frage

Ответы:

157

Этот ответ больше не применим, если вы не разрабатываете для очень старого устройства iOS ... См. Другие решения


Ответ 2011 года: для веб-приложения / html-приложения, работающего в iOS Safari, вам нужно что-то вроде

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

Для iOS 5 вы можете принять во внимание следующее: document.ontouchmove и прокрутка в iOS 5.

Обновление от сентября 2014 г. Более подробный подход можно найти здесь: https://github.com/luster-io/prevent-overscroll . Для этого и множества полезных советов по веб-приложениям см. Http://www.luster.io/blog/9-29-14-mobile-web-checklist.html.

Обновление март 2016 г .: эта последняя ссылка больше не активна - см. Https://web.archive.org/web/20151103001838/http://www.luster.io/blog/9-29-14-mobile-web-checklist .html для заархивированной версии. Спасибо @falsarella за указание на это.

Оскар Остегард
источник
1
У меня есть веб-приложение, работающее внутри iOS Safari, и я попытался отключить событие ontouchmove, но все еще можно увидеть эффект отскока, если все сделать осторожно. (iOS 5)
Nilesh 02
7
А как насчет того, чтобы просто отключить эффект отскока ...?
Yuval A.
6
Проблема с этим подходом заключается в том, что прокручиваемые div в вашем dom больше не будут прокручиваться. В зависимости от настроек вашего dom есть способы обойти это.
huesforalice
3
Здесь куча людей спрашивает о прокрутке div при использовании этого, поэтому ... чтобы сделать эти div прокручиваемыми, добавьте. onTouchMove: function(e) { e.stopPropagation(); e.stopImmediatePropagation(); } Это предотвратит попадание события в тело, но тело останется непрыгающим. Изменить: предполагается, что вы установили $ ('div'). On ('touchmove', ... onTouchMove);
Мэтт Кенефик
1
@OskarAustegard Последняя ссылка у меня не сработала, но я смог найти контент в веб-архиве: web.archive.org/web/20151103001838/http://www.luster.io/blog/…
falsarella
116

Вы также можете изменить положение body / html на фиксированное:

body,
html {
  position: fixed;
}
Бен Бос
источник
2
Это действительно очень хорошо работало на iPad iOS 8.2 Safari; больше нет эффекта отскока.
Аксели Пален
3
Лучший способ сделать это, что я видел до сих пор
hildende
8
Не работает, если вы хотите разместить что-то с position: absolute и всеми сторонами, установленными на 0 (чтобы сделать полноэкранный div) - весь ваш документ сжимается до нуля.
riv
4
Когда я использую это, страница переходит обратно в верхнюю часть страницы, а затем я сосредотачиваюсь на вводе. Вы знаете способ обойти это?
Джули
1
@riv добавляет ширину: 100%; height: 100% и body, и html мне помогли.
Тим
58

Чтобы предотвратить прокрутку в современных мобильных браузерах, вам нужно добавить passive: false. Я выдергивал волосы, заставляя это работать, пока не нашел это решение. Я нашел это только в одном месте в Интернете.

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

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

Кристофер Викерс
источник
7
Без { passive: false }него точно не работает !!! Добро пожаловать на StackOverflow, чувак
Ser
2
Я благодарен вам за это решение!
Пол З.
6
Это правильный ответ. Вы можете увидеть объяснение здесь: developer.mozilla.org/en-US/docs/Web/API/EventTarget/ ... после того, как Chrome 54 touchmove по умолчанию установил пассивное значение в true, что означает, что вызовы preventDefault будут игнорироваться. Вот почему вы должны передать {passive: false}, чтобы вызов preventDefault не игнорировался.
derickito
1
Вы объявляете функцию в JS - но как вы вызываете эту функцию в элементе, чтобы она работала, как предлагается?
ikwyl6
4
Это отлично работает, если вы хотите отключить все виды прокрутки. Но что, если я хочу отключить прокрутку только тела и сохранить возможность прокрутки элемента с помощью overflow-y: scroll? Например, наличие модального окна с большей высотой просмотра, чем тело.
Calsal
7

Для этого вы можете использовать этот фрагмент кода jQuery:

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

Это заблокирует вертикальную прокрутку, а также любой эффект возврата на ваши страницы.

Алессандро Инкарнати
источник
11
Это не Javascript, это jQuery. Вы должны упомянуть, что не все используют эту структуру.
inta
как я могу остановить горизонтальный отскок или прокрутку
Фидель Кастро
Горизонтальную прокрутку можно даже отключить с помощью CSS, применив overflow-x: hidden; в ваш основной контейнер. Я заметил, что в последних версиях сафари вы не можете отключить эффект отскока. Это встроенная функция браузера на мобильных устройствах.
Алессандро Инкарнати,
6
@inta Просто говорю, что это на самом деле javascript. Это просто не чистый javascript.
Бен Лорантфи
6
overflow: scroll;
-webkit-overflow-scrolling: touch;

В контейнере вы можете установить эффект отскока внутри элемента

Источник: http://www.kylejlarson.com/blog/2011/fixed-elements-and-scrolling-divs-in-ios-5/

user956584
источник
1
Вместе с overflow:hiddenтем <body>, это все еще лучшее решение. Однако при открытии клавиатуры или скольжении по нижней части экрана она больше не будет работать.
Фабиан фон Эллертс
попробуйте ввод onfocus удалить переполнение
user956584
4

Я знаю, что это немного нестандартно, но я использовал Swiffy для преобразования Flash в интерактивную игру HTML5 и столкнулся с той же проблемой прокрутки, но не нашел решений, которые работали бы.

Проблема заключалась в том, что этап Swiffy занимал весь экран, поэтому, как только он загрузился, событие touchmove документа никогда не запускалось.

Если я пытался добавить это же событие в контейнер Swiffy, оно заменялось сразу после загрузки сцены.

В конце концов я решил это (довольно беспорядочно), применив событие touchmove к каждому DIV на сцене. Поскольку эти div также постоянно менялись, мне нужно было постоянно их проверять.

Это было мое решение, которое, кажется, работает хорошо. Надеюсь, это поможет всем, кто пытается найти то же решение, что и я.

var divInterval = setInterval(updateDivs,50);
function updateDivs(){
$("#swiffycontainer > div").bind(
    'touchmove',
     function(e) {
        e.preventDefault();
    }
);}
Том
источник
это отключает всю прокрутку на ipad
Фидель Кастро
3

Код для удаления ipad safari: отключите прокрутку и эффект отскока

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

Если у вас есть холст тег внутри документа, где- то это будет влиять на удобство объекта внутри Canvas (например: движение объекта); поэтому добавьте ниже код, чтобы исправить это.

    document.getElementById("canvasId").addEventListener("touchmove", function (e) {
        e.stopPropagation();
    }, { passive: false });
Теджу В.Б.
источник
2

Попробуйте это решение 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();
    }
});

Предотвращает прокрутку и жесты отскока в Safari по умолчанию без отключения прослушивателей событий касания.

Андрей Вербицкий
источник
Это останавливает полную прокрутку веб-приложения элемента body.
MartijnICU
2

ни одно из решений у меня не работает. Вот как я это делаю.

  html,body {
      position: fixed;
      overflow: hidden;
    }
  .the_element_that_you_want_to_have_scrolling{
      -webkit-overflow-scrolling: touch;
  }
сердитый киви
источник
Я бы сделал .the_element_that_you_want_to_have_scrolling {scrolling: touch; }
Рой Сегалл
Ваш ответ сработал для меня для html, body, но я не могу прокрутить "the_element_that_you_want_to_have_scrolling". Этот элемент вложен в несколько разделов, находящихся под телом. Имеет ли значение, какие типичные теги элементов будут для этого вложенного div, который я хочу прокрутить? Положение: относительное.
ikwyl6
1

Для тех, кто использует MyScript в веб-приложении и борется с прокруткой / перетаскиванием тела (на iPad и планшетах) вместо того, чтобы писать:

<body touch-action="none" unresolved>

Это исправило это для меня.

Miro
источник
1

Вы можете использовать js для предотвращения прокрутки:

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

И чем просто запустить / остановить toggleScrollфункцию при открытии / закрытии модального окна.

Как это toggleScroll(true) / toggleScroll(false)

(Это только для iOS, на Android не работает)

Влад Новиков
источник
1

Попробуйте это решение JS, которое переключает webkitOverflowScrollingстиль. Хитрость здесь в том, что этот стиль отключен, мобильный Safari переходит на обычную прокрутку и предотвращает чрезмерный отскок - увы, он не может отменить текущее перетаскивание. Это сложное решение также отслеживает, onscrollкак отскок сверху создает scrollTopнегатив, который можно отследить. Это решение было протестировано на iOS 12.1.1 и имеет единственный недостаток: при ускорении прокрутки все еще происходит одиночный избыточный отскок, поскольку сброс стиля может не отменить его немедленно.

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

улучшенный ответ @Ben Bos и прокомментированный @Tim

Этот CSS поможет предотвратить прокрутку и проблемы с производительностью при повторном рендеринге CSS, потому что положение изменилось / небольшое отставание без ширины и высоты

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

Auronsan Zenx
источник
На IOS13 это самое чистое решение для меня, и пока не обнаружено никаких недостатков ...
Сойлент Грэм
0

Для тех из вас, кто не хочет избавляться от подпрыгивания, а просто хочет знать, когда он останавливается (например, чтобы начать вычисление расстояний до экрана), вы можете сделать следующее (контейнер - это переполняющийся элемент контейнера):

    const isBouncing = this.container.scrollTop < 0 ||
    this.container.scrollTop + this.container.offsetHeight >
        this.container.scrollHeight
Фил
источник
0

Отключить эффект прокрутки сафари отскоком:

html,
body {
  height: 100%;
  width: 100%;
  overflow: auto;
  position: fixed;
}  
Абольфазл Багшахи
источник
-1

Подобно сердитому киви, я заставил его работать с использованием высоты, а не положения:

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

.the_element_that_you_want_to_have_scrolling{
  -webkit-overflow-scrolling: touch;
}
austinh7
источник
как указано в документе, это позволит отскок также после того, как импульс не отключен
CaSUaL
@CaSUaL Не уверен, что вы имеете в виду? Это решение сработало для моего
варианта
-1

Решение протестировано, работает на iOS 12.x

Это проблема, с которой я столкнулся:

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

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

  </article>
</body>

Пока я прокручиваю свою галерею, тело всегда прокручивается само (человеческий жест не совсем горизонтален), что делает мою галерею бесполезной.

Вот что я сделал, пока моя галерея начала прокручиваться

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

И когда моя галерея перестанет прокручиваться ...

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

Надеюсь, это поможет ~

RRTW
источник