[英]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.