How to prevent 'Overscroll history navigation' without preventing touchstart?

拜拜、爱过 提交于 2019-12-22 09:57:33

问题


I'm implementing a swipe-base navigation, and I'm running into trouble with Chrome.

A newly implemented feature, 'Overscroll history navigation', is triggered when the page is dragged to the right, causing a jump back (to 'history -1'). To prevent this, I'd have to call .preventDefault() on touchstart, but this also disables everything from clicking links to scrolling. How do I prevent browser UI events without interfering with the standard page?

Disabling the feature altogether by setting the appropriate flag in chrome fixes the issue, but isn't practical for a public-facing application. chrome://flags/#overscroll-history-navigation


回答1:


I eventually figured out a solution:

Chrome fires at least touchstart and touchmove before overscrolling. By tracking the direction of those events, an overscroll can be filtered from regular scrolling.

I've written up the code for this Hammer.js issue.




回答2:


I used

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

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




回答3:


To leave scrolling vertical working and moving elemets horizontally you need to check if moving is more along x then y axis by comparing coordinates differences using Math.abs(), then decide to call .preventDefault() in touchmove event or not.

Sounds little strange but i think it is the only way to control this behemoth feature "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);
});

Complete example to test on touch devices: DEMO




回答4:


  • listen to onscroll event on the container and store the 'scrollLeft' value this.offsetX = event.currentTarget.scrollLeft;
  • listen to onwheel event on the same container and use this handler

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>


来源:https://stackoverflow.com/questions/23560528/how-to-prevent-overscroll-history-navigation-without-preventing-touchstart

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!