如何找到touchmove javascript事件的实际event.target?
=我正在尝试在web应用程序中开发一个简单的拖放UI。可以用鼠标或手指拖动项目,然后将其放入多个放置区域之一。将项目拖过放置区域(但尚未释放)时,该区域将高亮显示,并标记安全着陆位置。这对于鼠标事件来说非常好,但我仍然坚持使用iPhone/iPad上的touchstart/touchmove/touchend系列 问题是,当调用项的ontouchmove事件处理程序时,它的如何找到touchmove javascript事件的实际event.target?,javascript,dom-events,Javascript,Dom Events,=我正在尝试在web应用程序中开发一个简单的拖放UI。可以用鼠标或手指拖动项目,然后将其放入多个放置区域之一。将项目拖过放置区域(但尚未释放)时,该区域将高亮显示,并标记安全着陆位置。这对于鼠标事件来说非常好,但我仍然坚持使用iPhone/iPad上的touchstart/touchmove/touchend系列 问题是,当调用项的ontouchmove事件处理程序时,它的event.touch[0]。target始终指向原始HTML元素(项),而不是当前位于手指下的元素。此外,当一个项目被手指
event.touch[0]。target
始终指向原始HTML元素(项),而不是当前位于手指下的元素。此外,当一个项目被手指拖过某个放置区域时,该放置区域自己的touchmove
处理程序根本不会被调用。这基本上意味着我无法确定手指何时位于任何放置区域之上,因此无法根据需要突出显示它们。同时,当使用鼠标时,mousedown
正确地为光标下的所有HTML元素触发
有些人确认它应该是这样工作的,例如:
对于那些来自普通web设计世界的人来说,在普通的mousemove事件中,传递到目标属性中的节点通常是鼠标当前所在的位置。但在所有iphonetouch事件中,目标是对发起节点的引用
问题:有没有办法确定手指下的实际元素(而不是最初接触的元素,在许多情况下可能会有所不同)?这肯定不是事件目标应该如何工作的。还有一个DOM不一致性,我们现在可能永远都会遇到,这是由于一个供应商在闭门进行扩展时没有进行任何审查 使用
document.element frompoint
解决此问题
document.elementFromPoint(event.clientX, event.clientY);
我在Android上也遇到过同样的问题(WebView+Phonegap)。我希望能够拖动元素并检测它们何时被拖动到某个其他元素上。 出于某种原因,触摸事件似乎忽略了
指针事件
属性值
鼠标:
- 如果设置了
,则pointer events=“visiblePainted”
将指向被拖动的元素event.target
- 如果设置了
,则pointer events=“none”
将指向被拖动元素(我的拖动区域)下的元素event.target
指针事件
属性的原因
触摸:
始终指向被拖动的元素,无论event.target
值是否错误指针事件
- 对于鼠标事件,我只是按原样重用鼠标事件
- 对于触摸事件,我使用:
DragAndDrop.prototype.getDragEventFromTouch = function (event) { var touch = event.touches.item(0); return { screenX: touch.screenX, screenY: touch.screenY, clientX: touch.clientX, clientY: touch.clientY, pageX: touch.pageX, pageY: touch.pageY, target: document.elementFromPoint(touch.screenX, touch.screenY) }; };
然后将其用于处理(检查被拖动的对象是否在我的拖动区域中)。出于某种原因,
document.elementFromPoint()
即使在Android上也似乎尊重指针事件
值。2010年的公认答案不再有效:touchmove
没有clientX
或clientY
属性。(我猜过去是这样,因为答案有很多赞成票,但现在没有。)
目前的解决办法是:
var myLocation = event.originalEvent.changedTouches[0];
var realTarget = document.elementFromPoint(myLocation.clientX, myLocation.clientY);
在以下方面进行测试和工作:
- iOS上的狩猎
- iOS上的Chrome
- Android上的Chrome
- 支持触摸屏的Windows桌面上的Chrome
- 触摸式Windows桌面上的FF
- 支持触摸屏的Windows桌面上的IE
- Windows Phone
- 鼠标移动=“悬停”类似行为
- 触摸移动=“拖动”类似行为
element:hover {
background-color: yellow;
}
这就是为什么当用户用一根手指触摸屏幕时,第一个事件(touchstart)会获取目标元素,随后的事件(touchmove)会保留对触摸开始的原始元素的引用。这感觉是错误的,但有这样的逻辑,你可能需要原始的目标信息以及。所以理想情况下,在未来应该有两个(源目标和当前目标)可用
因此,今天(2018年)屏幕可以同时使用鼠标和触摸屏的常见做法仍然是连接两个监听器(鼠标和触摸),然后“规范化”事件坐标,并使用上述浏览器api查找这些坐标中的元素:
// get coordinates depending on pointer type:
var xcoord = event.touches? event.touches[0].pageX : event.pageX;
var ycoord = event.touches? event.touches[0].pageY : event.pageY;
// get element in coordinates:
var targetElement = document.elementFromPoint(xcoord, ycoord);
// validate if this is a valid element for our case:
if (targetElement && targetElement.classList.contains("dropZone")) {
}
非常感谢你!这就是我需要的。我还想为那些面临同样问题的人分享更多的魔法:在可拖动元素上添加“指针事件:无”,使elementFromPoint通过它并抓住真正的目标。我认为很明显,这是一种性能折衷。考虑移动设备显然需要做的额外处理,以便正确地确定在由硬件提供的每秒60次的点下的元素。它几乎需要DOM树遍历和AABB点检查(可以很快地完成)。我的猜测是,从苹果公司的角度来看,无论活动目标是否按预期运行,缓慢而多变的活动表现都不如轻松的过火