如何找出touchmove javascript事件的实际event.target?
我正试图在我的web应用程序中开发一个简单的拖放用户界面。 一个项目可以通过鼠标或手指拖动,然后可以放入几个拖放区之一。 当物品被拖放到拖放区域(但还没有被释放)时,该区域被突出显示,标记安全着陆位置。 这对鼠标事件来说非常合适,但是我在iPhone / iPad上遇到了touchstart / touchmove / touchend系列。
问题是,当一个项目的ontouchmove事件处理程序被调用时,它的event.touches[0].target
总是指向原始的HTML元素(项目),而不是当前在手指下的元素。 而且,当某个项目被手指拖放到某个拖放区时,该拖放区自己的touchmove
处理程序根本不会被调用。 这基本上意味着我不能确定何时手指在任何拖放区域之上,因此不能根据需要突出显示它们。 同时,在使用鼠标的时候, mousedown
被正确的触发了光标下的所有HTML元素。
有些人确认,它应该像这样工作,例如http://www.sitepen.com/blog/2008/07/10/touching-and-gesturing-on-the-iphone/ : 对于你来自那些正常的网页devise世界中,在正常的鼠标移动事件中,传递给目标属性的节点通常是鼠标当前所在的部分。 但在所有的iPhone touch事件中,目标是对始发节点的引用。
问题:有什么方法可以确定手指下的实际元素(而不是最初触摸的元素,在许多情况下可能会有所不同)?
这当然不是事件目标应该如何工作的。 然而,由于供应商在没有任何审查的情况下提供了closures的扩展,所以我们现在可能永远坚持的另一个DOM不一致。
使用document.elementFromPoint
来解决它。
document.elementFromPoint(event.clientX, event.clientY);
2010年接受的答案不再有效: touchmove
没有clientX
或clientY
属性。 (我猜它已经习惯了,因为答案有许多upvotes,但它目前不)。
目前的解决scheme是
var myLocation = event.originalEvent.changedTouches[0]; var realTarget = document.elementFromPoint(myLocation.clientX, myLocation.clientY);
经过testing和工作:
- iOS上的Safari
- iOS上的Chrome
- Android上的Chrome
- 支持触摸的Windows桌面上的Chrome
- 在支持触摸的Windows桌面上使用FF
不适用于:
- IE在启用了触摸的Windows桌面上
未经testing:
- Windows Phone
我在Android(WebView + Phonegap)上遇到了同样的问题。 我希望能够拖动元素并检测它们何时被拖动到某个其他元素上。 由于某些原因,触摸事件似乎忽略了pointer-events
属性值。
老鼠:
- 如果设置了
pointer-events="visiblePainted"
,那么event.target
将指向拖动的元素。 - 如果设置了
pointer-events="none"
,那么event.target
将指向拖拽元素(我的拖拽区域)下的元素,
这是事情应该如何工作,为什么我们有第一个pointer-events
属性。
触摸:
-
event.target
总是指向拖动的元素,无论pointer-events
值,恕我直言,错误。
我的解决方法是创build我自己的拖动事件对象(鼠标和触摸事件的通用接口),其中包含事件坐标和目标:
- 对于鼠标事件,我只是重复使用鼠标事件
-
对于触摸事件我使用:
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上似乎也遵守pointer-events
值。