如何找到touchmove javascript事件的实际event.target?

如何找到touchmove javascript事件的实际event.target?,javascript,dom-events,Javascript,Dom Events,=我正在尝试在web应用程序中开发一个简单的拖放UI。可以用鼠标或手指拖动项目,然后将其放入多个放置区域之一。将项目拖过放置区域(但尚未释放)时,该区域将高亮显示,并标记安全着陆位置。这对于鼠标事件来说非常好,但我仍然坚持使用iPhone/iPad上的touchstart/touchmove/touchend系列 问题是,当调用项的ontouchmove事件处理程序时,它的event.touch[0]。target始终指向原始HTML元素(项),而不是当前位于手指下的元素。此外,当一个项目被手指

=我正在尝试在web应用程序中开发一个简单的拖放UI。可以用鼠标或手指拖动项目,然后将其放入多个放置区域之一。将项目拖过放置区域(但尚未释放)时,该区域将高亮显示,并标记安全着陆位置。这对于鼠标事件来说非常好,但我仍然坚持使用iPhone/iPad上的touchstart/touchmove/touchend系列

问题是,当调用项的ontouchmove事件处理程序时,它的
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

所以触摸事件在互动方面有不同的“理念”:

  • 鼠标移动=“悬停”类似行为
  • 触摸移动=“拖动”类似行为
这种差异来自这样一个事实,如果在它之前没有touchstart事件,则不可能有一个touchmove,因为用户必须触摸屏幕才能启动此交互。当然,用户可以使用鼠标在屏幕上移动鼠标,而无需按下按钮(mousedown事件)

这就是为什么我们基本上不希望在触摸中使用悬停效果:

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点检查(可以很快地完成)。我的猜测是,从苹果公司的角度来看,无论活动目标是否按预期运行,缓慢而多变的活动表现都不如轻松的过火