繁体   English   中英

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

[英]How to prevent 'Overscroll history navigation' without preventing touchstart?

我正在实施基于滑动的导航,但在 Chrome 上遇到了麻烦。

新实现的功能“Overscroll history navigation”在页面向右拖动时触发,导致跳回(到“history -1”)。 为了防止这种情况,我不得不打电话.preventDefault()touchstart ,但这也禁止一切从点击链接到滚动。 如何在不干扰标准页面的情况下阻止浏览器 UI 事件?

通过在 chrome 中设置适当的标志来完全禁用该功能可以解决问题,但对于面向公众的应用程序来说并不实用。 chrome://flags/#overscroll-history-navigation

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

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

我已经为这个 Hammer.js 问题编写了代码。

我用了

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

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

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

听起来有点奇怪,但我认为这是控制这个庞然大物功能“过度滚动历史导航”的唯一方法。 可以。

$(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

  • 侦听容器上的onscroll事件并存储 'scrollLeft' 值this.offsetX = event.currentTarget.scrollLeft;
  • 侦听同一个容器上的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(); } });
 .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; }
 <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>

它是“touchmove”,您必须在回调中停止传播()和防止默认(),您可以调用任何需要检查滑动和导航发生的内容。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM