我正在实现滑动导航,我在Chrome上遇到了麻烦。
一个新实现的功能,"超滚动历史导航",当页面被拖到右边时触发,导致跳回("历史-1")。为了防止这种情况,我必须在touchstart
上调用.preventDefault()
,但这也禁用了从点击链接到滚动的所有操作。如何在不干扰标准页面的情况下防止浏览器UI事件?
通过在chrome中设置适当的标志来完全禁用该功能可以解决这个问题,但对于面向公众的应用程序来说是不切实际的。chrome://标志/# overscroll-history-navigation
我终于想出了一个解决办法:
Chrome在过度滚动之前至少触发touchstart
和touchmove
。通过跟踪这些事件的方向,可以从常规滚动中过滤出过度滚动。
我已经为这个Hammer.js问题写好了代码
要保持垂直滚动工作和水平移动元素,您需要通过使用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>
我用
html, body {
width: 100%;
height: 100%;
margin: 0;
overscroll-behavior: contain;
}
https://developer.mozilla.org/en-US/docs/Web/CSS/overscroll-behavior 这是'touchmove'你将不得不stopPropagation()和preventDefault()内的回调,你可以调用任何你需要检查滑动和导航发生