通过指针事件支持在可滚动 div 中拖动和平移
Supporting dragging and panning in a scrollable div with Pointer Events
考虑可滚动区域中可拖动 div 的情况。当您触摸 div 内部时,进一步的手指移动应将 div 拖到该区域周围。当您在 div 之外触摸时,进一步的手指移动应该会平移可滚动区域。
我有一个 JSFiddle 来说明这一点。使用鼠标,我可以轻松地拖动 div,但触摸事件似乎也不起作用。
注意:我在 fiddle 中使用指针事件,因此如果您使用的浏览器不支持它们,则 fiddle 可能看起来已损坏。
有谁知道如何正确实现这种交互?
http://jsfiddle.net/mrmills/13t34jsv/
HTML:
<div id="scroll-outer">
<div id="scroll-inner">
<div id="handle">
</div>
</div>
</div>
CSS:
#scroll-outer { width: 400px; height: 400px; overflow: auto }
#scroll-inner { width: 2000px; height: 2000px }
#handle { width: 44px; height: 44px; background-color: rgba(0,0,0,0.5) }
JS:
function pointerDown(ev) {
scrollInner.addEventListener("pointermove", pointerMove);
scrollInner.addEventListener("pointerup", pointerUp);
dragStartX = ev.pageX; dragStartY = ev.pageY;
}
function pointerMove(ev) {
handle.style.transform = "translate3d(" +
(x + ev.pageX - dragStartX) + "px, " +
(y + ev.pageY - dragStartY) + "px, 0)";
}
function pointerUp(ev) {
scrollInner.removeEventListener("pointermove", pointerMove);
scrollInner.removeEventListener("pointerup", pointerUp);
x = x + ev.pageX - dragStartX;
y = y + ev.pageY - dragStartY;
}
var x = 0;
var y = 0;
var dragStartX = 0;
var dragStartY = 0;
var handle = document.getElementById("handle");
var scrollInner = document.getElementById("scroll-inner");
handle.addEventListener("pointerdown", pointerDown);
要在元素上使用基于触摸的输入触发指针事件,您需要在该元素上设置 CSS 属性 touch-action: none
(默认为 auto
)。
在您的情况下,在 div#handle
上设置 touch-action: none
将使其可拖动。
添加:如果您使用 PEP,则必须向元素添加 HTML 数据属性 touch-action="none"
,例如:
...
<div id="handle" touch-action="none"></div>
...
考虑可滚动区域中可拖动 div 的情况。当您触摸 div 内部时,进一步的手指移动应将 div 拖到该区域周围。当您在 div 之外触摸时,进一步的手指移动应该会平移可滚动区域。
我有一个 JSFiddle 来说明这一点。使用鼠标,我可以轻松地拖动 div,但触摸事件似乎也不起作用。
注意:我在 fiddle 中使用指针事件,因此如果您使用的浏览器不支持它们,则 fiddle 可能看起来已损坏。
有谁知道如何正确实现这种交互?
http://jsfiddle.net/mrmills/13t34jsv/
HTML:
<div id="scroll-outer">
<div id="scroll-inner">
<div id="handle">
</div>
</div>
</div>
CSS:
#scroll-outer { width: 400px; height: 400px; overflow: auto }
#scroll-inner { width: 2000px; height: 2000px }
#handle { width: 44px; height: 44px; background-color: rgba(0,0,0,0.5) }
JS:
function pointerDown(ev) {
scrollInner.addEventListener("pointermove", pointerMove);
scrollInner.addEventListener("pointerup", pointerUp);
dragStartX = ev.pageX; dragStartY = ev.pageY;
}
function pointerMove(ev) {
handle.style.transform = "translate3d(" +
(x + ev.pageX - dragStartX) + "px, " +
(y + ev.pageY - dragStartY) + "px, 0)";
}
function pointerUp(ev) {
scrollInner.removeEventListener("pointermove", pointerMove);
scrollInner.removeEventListener("pointerup", pointerUp);
x = x + ev.pageX - dragStartX;
y = y + ev.pageY - dragStartY;
}
var x = 0;
var y = 0;
var dragStartX = 0;
var dragStartY = 0;
var handle = document.getElementById("handle");
var scrollInner = document.getElementById("scroll-inner");
handle.addEventListener("pointerdown", pointerDown);
要在元素上使用基于触摸的输入触发指针事件,您需要在该元素上设置 CSS 属性 touch-action: none
(默认为 auto
)。
在您的情况下,在 div#handle
上设置 touch-action: none
将使其可拖动。
添加:如果您使用 PEP,则必须向元素添加 HTML 数据属性 touch-action="none"
,例如:
...
<div id="handle" touch-action="none"></div>
...