如何在不阻止touchstart的情况下防止“过度滚动历史导航”?

时间:2014-05-09 09:00:18

标签: javascript google-chrome touch preventdefault

我正在实施基于滑动的导航,而且我遇到了Chrome问题。

当页面向右拖动时,会触发新实现的功能“超级滚动历史记录导航”,从而导致跳回(到历史记录-1')。为了防止这种情况发生,我必须在.preventDefault()上调用touchstart,但这也会禁用从点击链接到滚动的所有内容。 如何在不干扰标准页面的情况下阻止浏览器UI事件?

通过在chrome中设置适当的标记来完全禁用该功能可以解决问题,但对于面向公众的应用程序来说并不实用。 铬://标志/#反弹时历史导航

5 个答案:

答案 0 :(得分:2)

我最终想出了一个解决方案:

在过度滚动之前,Chrome会至少触发touchstarttouchmove。通过跟踪这些事件的方向,可以从常规滚动中过滤过量滚动。

我已经写了代码for this Hammer.js issue

答案 1 :(得分:1)

我用过

html, body {
    width: 100%;
    height: 100%;
    margin: 0;
    overscroll-behavior: contain;    
}

https://developer.mozilla.org/en-US/docs/Web/CSS/overscroll-behavior

答案 2 :(得分:0)

要保持滚动垂直工作并水平移动元素,您需要通过使用Math.abs()比较坐标差异来检查x和y轴之间的移动是否更多,然后决定是否在touchmove事件中调用.preventDefault()。

听起来有点奇怪,但我认为这是控制这个巨大功能的唯一方法" Overscroll history navigation"。 BLE。

$(function () {

    function extract(e) {
        if (e.changedTouches) {
            e = e.changedTouches;
            if (e['0'])
                e = e['0'];
        }
        return e;
    }

    var div = $('div').html('Drag me left and right and see that Overscroll is disabled & drag me up and down to see that scroll still works<br /><br /><br />'.repeat(300));
    var di  = div.get(0); // get native dom element

    var startx, lastx, lasty, l = false, active = false;

    di.addEventListener("touchstart", function (e) {
        active = true;
        e = extract(e);

        // init
        lastx = e.pageX;
        lasty = e.pageY;

        l = parseInt(div.css('left'), 10);
        startx = e.pageX;
    }, false);

    di.addEventListener("touchmove", function (ee) {
        if (active) {
            var e = extract(ee);

            // check if preventDefault to cancel Overscroll history navigation only if it's needed
            if (Math.abs(lastx - e.pageX) > Math.abs(lasty - e.pageY)) {
                ee.preventDefault();
            }

            // update x y to next above calculation
            lastx = e.pageX;
            lasty = e.pageY;

            // repositioning
            div.css({left: (l + (e.pageX - startx))+'px'})
        }
    }, false);

    di.addEventListener("touchend", function (e) {
        active = false;
    }, false);
});

在触控设备上测试的完整示例:DEMO

答案 3 :(得分:0)

  • 在容器上收听this.offsetX = event.currentTarget.scrollLeft;事件并存储&#39; scrollLeft&#39;值 onwheel
  • 在同一容器上侦听var offset = 0; document.getElementById("1") .addEventListener("scroll", function(event) { offset = event.currentTarget.scrollLeft; }); document.getElementById("1") .addEventListener("wheel", function(event) { // if we reach the left side of the scrollable content, and we scroll further -> block the event if (offset === 0 && event.deltaX <= 0) { event.preventDefault(); } }); 事件并使用此处理程序

&#13;
&#13;
.container {
  width: 100%;
  background-color: blue;
  overflow: auto;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
}

.element {
  display: inline-block;
  min-width: 100px;
  height: 50px;
  margin: 10px;
  background-color: red;
}
&#13;
<div id="1" class="container">
  <div class="element">
  1
  </div>
  <div class="element">
  2
  </div>
  <div class="element">
  3
  </div>
  <div class="element">
  4
  </div>
  <div class="element">
  5
  </div>
  <div class="element">
  6
  </div>
  <div class="element">
  7
  </div>
  <div class="element">
  8
  </div>
</div>
&#13;
create table A (x varchar2(4000));

insert into A values ('select p,q,r from o');
commit;
&#13;
&#13;
&#13;

答案 4 :(得分:0)

这是'touchmove',您必须在回调内停止stopPropagation()和preventDefault(),然后才能调用所需的任何内容来检查滑动和导航。