ipad苹果浏览器:禁用滚动和弹跳效果?


126

我正在开发基于浏览器的应用程序,目前正在为ipad Safari浏览器开发和设计样式。

我正在ipad上寻找两件事:如何为不需要的页面禁用垂直滚动?&如何禁用弹性弹跳效果?


请参阅下面的答案只有一个工作对我来说,是电流(stackoverflow.com/a/51176339/1979180
FRAGE

Answers:


157

除非您正在开发非常旧的iOS设备,否则此答案不再适用。请参阅其他解决方案


2011年答案:对于在iOS Safari中运行的Web / html应用程序,您需要类似

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

对于iOS 5,您可能需要考虑以下因素:document.ontouchmove并在iOS 5上滚动

2014年9月更新:可在以下网址找到更彻底的方法:https : //github.com/luster-io/prevent-overscroll。有关此以及大量有用的Web应用程序建议,请参阅http://www.luster.io/blog/9-29-14-mobile-web-checklist.html

2016年3月更新:该最后一个链接不再有效-请参阅https://web.archive.org/web/20151103001838/http://www.luster.io/blog/9-29-14-mobile-web-checklist .html作为存档版本。感谢@falsarella指出这一点。


1
我在iOS Safari中运行了webapp,并且尝试禁用ontouchmove事件,但是如果仔细完成,仍然有可能看到反弹效果。(iOS 5)
Nilesh 2012年

7
只是禁用反弹效果呢?
Yuval A.

6
这种方法的问题是,您的dom中的可滚动div将不再滚动。根据您的dom设置,有一些解决方法。
huesforalice 2014年

3
这里有很多人问滚动div时要使用它,以便使这些div可滚动,请添加onTouchMove: function(e) { e.stopPropagation(); e.stopImmediatePropagation(); } 它可以防止事件击中主体,但是主体将保持非弹性。编辑:这是假设您设置$('div')。on('touchmove',... onTouchMove);
Matt Kenefick

1
@OskarAustegard最后一个链接对我不起作用,但是我可以在Web存档上找到内容:web.archive.org/web/20151103001838/http
//www.luster.io/blog/…– falsarella

116

您还可以将body / html的位置更改为fixed:

body,
html {
  position: fixed;
}

2
实际上,这在iPad iOS 8.2 Safari上效果很好。没有反弹效果了。
AkseliPalén2015年

3
到目前为止,我所见过的最好的方法
hildende 2015年

8
如果您想放置以下位置,则不起作用:绝对且所有面都设置为0(以形成全屏div)-您的整个文档将缩小为零。
riv

4
当我使用此页面时,页面会跳回到页面顶部,然后专注于输入。您知道解决这个问题的方法吗?
朱莉

1
@riv添加宽度:100%;身高:100%的身体和html对我都有帮助。
蒂姆(Tim)

57

为了防止在现代移动浏览器上滚动,您需要添加被动: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上的家伙
丝氨酸

2
感谢您提供此解决方案!
Paul Z.

6
这是正确的答案。您可以在此处查看说明:developer.mozilla.org/en-US/docs/Web/API/EventTarget/…在Chrome 54 touchmove之后,默认将被动设置为true,这意味着preventDefault调用将被忽略。这就是为什么必须传递{passive:false}的原因,因此preventDefault调用不会被忽略。
derickito

1
您在JS中声明了该函数-但是如何在元素上调用此函数以使其按建议工作呢?
ikwyl6 '19

4
如果您想禁用所有类型的滚动,则效果很好。但是,如果我只想禁用身体上的滚动并保持在元素上滚动的可能性overflow-y: scroll怎么办?例如,具有比主体高的视图高度的模态。
Calsal

7

您可以使用以下jQuery代码片段执行此操作:

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

这将阻止垂直滚动以及页面上发生的任何反弹效果。


11
这不是Javascript,而是jQuery。您应该提到,并非每个人都在使用该框架。
2014年

我如何停止水平弹跳或滚动
Fidel castro 2014年

您甚至可以使用css禁用水平滚动,应用overflow-x:hidden;。到您的主容器。我注意到在最新版本的safari中,您无法禁用弹跳效果。这是移动设备上浏览器的本机功能。
亚历山德罗·Incarnati 2014年

6
@inta只是说这实际上是javascript。这不是纯JavaScript。
本·洛兰特


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中的整个滚动
fidel castro 2014年

3

删除ipad Safari的代码:禁用滚动和跳动效果

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

如果文档中有canvas标签,则有时会影响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滚动和跳动手势而不会断开您的触摸事件监听器。


这将阻止Web应用程序在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 {滚动:触摸;}
Roy Segall '18

您的答案对html,body来说对我有用,但是我无法滚动“ the_element_that_you_want_to_have_scrolling”。该元素嵌套在主体下面的一些div中。我想让此div滚动的嵌套div的任何典型元素标签有关系吗?我的位置:相对。
ikwyl6


1

对于那些正在使用MyScript Web应用程序并且正忙于滚动/拖动正文(在iPad和Tablets上)而不是实际书写的用户:

<body touch-action="none" unresolved>

这为我解决了。


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

试试这个切换webkitOverflowScrolling样式的JS解决方案。这里的技巧是关闭这种样式,移动Safari可以进行普通滚动并防止过度弹跳-a,它无法取消正在进行的拖动。这种复杂的解决方案还可以跟踪,因为可能会跟踪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%
}


在IOS13上,这对我来说是最干净的解决方案,尚未发现任何缺点……
Soylent Graham

0

对于那些不想摆脱反弹而只是想知道反弹何时停止的人(例如,开始计算屏幕距离),您可以执行以下操作(容器是溢出的容器元素):

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


-1

类似于生气的猕猴桃,我使它使用高度而不是位置来工作:

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

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

作为文档,这还将在动量
不禁用

@CaSUaL不确定您的意思吗?此解决方案适用于我的用例……
austinh7 '18

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

希望这会有所帮助〜

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.