我有一个javascript circuit simulator,您可以通过拖动大门来编辑电路。有时电路变得非常大,因此它所绘制的画布元素超出了浏览器的视口并且滚动变得必要。
当带触摸屏的用户在屏幕上滑动手指时,我希望在电路元素上开始的幻灯片被解释为拖动。但是,从空白空间开始的幻灯片(由我的自定义逻辑确定是否显示在画布上)应该被解释为滚动。
如何让拖动和滚动行为和谐相处?我怎么做没有很好地模拟浏览器常用的滚动行为?用户讨厌滚动时w.r.t.本土行为。
(额外奖励:我如何在不改变通常的滚动行为但的同时仍然阻止滚动触发导航动作[例如在Android上拉下来时已经在页面顶部重新加载]它])
我只是在我希望画布控制并显示拖动时才尝试调用touchEvent.preventDefault
。滚动条出现后立即停止运行(浏览器发送触摸,但随后立即取消)。 CSS属性touch-action
也可能有用,但我还没有尝试过很多。
答案 0 :(得分:0)
我最终使用的解决方法是阻止div。
对于画布中的每个可拖动元素,我在该元素的位置上添加了一个touch-action: none
,opacity: 0
和position: absolute
的div。当用户触摸其中一个阻挡div时,滚动被阻止而不会干扰拖动事件。
setBlockers(blockers, overrideCursorStyle) {
// ensure enough blocker divs exist
while (this._blockerDivs.length < blockers.length) {
let blockerDiv = document.createElement('div');
blockerDiv.style.touchAction = 'none';
blockerDiv.style.position = 'absolute';
blockerDiv.style.opacity = 0;
this._parentElement.appendChild(blockerDiv);
this._blockerDivs.push(blockerDiv);
}
// reposition blocker divs
for (let i = 0; i < blockers.length; i++) {
let s = this._blockerDivs[i].style;
let {x, y, w, h, cursor} = blockers[i];
[s.left, s.top, s.width, s.height] = [x, y, w, h].map(e => e + "px");
s.cursor = overrideCursorStyle || cursor || 'auto';
s.display = 'inline';
}
// hide unused blocker divs
for (let i = blockers.length; i < this._blockerDivs.length; i++) {
this._blockerDivs[i].style.display = 'none';
}
}
这适用于Chrome,适用于iOS上的Safari,但不适用于Firefox(不支持触摸操作:无)。