如何找出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没有clientXclientY属性。 (我猜它已经习惯了,因为答案有许多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值。