Как узнать реальную event.target события touchmove javascript?
Я пытаюсь разработать простой интерфейс перетаскивания/перетаскивания в моем веб-приложении. Элемент можно перетаскивать мышью или пальцем, а затем можно отбрасывать в одну из нескольких зон выпадения. Когда элемент перетаскивается по зоне выпадения (но еще не выпущен), эта зона подсвечивается, маркируя безопасное место посадки. Это прекрасно работает с событиями мыши, но я застрял в семействе touchstart/touchmove/touchhend на iPhone/iPad.
Проблема заключается в том, что когда вызывается обработчик события ontouchmove, его event.touches[0].target
всегда указывает на исходный HTML-элемент (элемент), а не на элемент, который сейчас находится под пальцем. Более того, когда элемент перетаскивается пальцем по какой-либо зоне перетаскивания, этот дескриптор собственных обработчиков touchmove
вообще не вызывается. Это по существу означает, что я не могу определить, когда палец находится выше любой из зон падения, и поэтому не может выделить их по мере необходимости. В то же время при использовании мыши mousedown
корректно запускается для всех элементов HTML под курсором.
Некоторые люди подтверждают, что он должен работать так, например http://www.sitepen.com/blog/2008/07/10/touching-and-gesturing-on-the-iphone/:
Для тех из вас, кто пришел из обычного мира веб-дизайна, в обычном событии mousemove, node, переданном в целевом атрибуте, обычно является тем, что мышь в данный момент закончила. Но во всех событиях касания iPhone цель - это ссылка на исходный node.
Вопрос: есть ли способ определить фактический элемент под пальцем (НЕ изначально затронутый элемент, который может быть другим во многих случаях)?
Ответы
Ответ 1
Это, конечно, не то, как должны работать объекты событий. Еще одна несогласованность DOM, которую мы, вероятно, все время застряли навсегда, из-за того, что продавец придумывает расширения за закрытыми дверями без каких-либо обзоров.
Используйте document.elementFromPoint
, чтобы обойти его.
document.elementFromPoint(event.clientX, event.clientY);
Ответ 2
Принятый ответ 2010 года больше не работает: touchmove
не имеет атрибута clientX
или clientY
. (Я предполагаю, что это использовалось, так как ответ имеет несколько upvotes, но в настоящее время он отсутствует.)
Текущее решение:
var myLocation = event.originalEvent.changedTouches[0];
var realTarget = document.elementFromPoint(myLocation.clientX, myLocation.clientY);
Протестировано и работает над:
- Safari на iOS
- Chrome на iOS
- Chrome на Android
- Chrome на рабочем столе с сенсорным экраном
- FF на рабочем столе с сенсорным экраном
НЕ работает:
- IE на рабочем столе с сенсорным экраном
Не тестировалось:
Ответ 3
Я столкнулся с той же проблемой на Android (WebView + Phonegap). Я хочу иметь возможность перетаскивать элементы вокруг и обнаруживать, когда их перетаскивают через некоторый другой элемент.
По какой-то причине сенсорные события, похоже, игнорируют значение атрибута pointer-events
.
Мышь:
- Если
pointer-events="visiblePainted"
установлено, то event.target
будет указывать на перетаскиваемый элемент.
- Если
pointer-events="none"
установлено, то event.target
будет указывать на элемент под перетаскиваемым элементом (моя область перетаскивания)
Вот как должны работать вещи и почему у нас есть атрибут pointer-events
.
Touch:
-
event.target
всегда указывает на перетаскиваемый элемент, вне зависимости от значения pointer-events
, которое не соответствует IMHO.
Моим обходным путем является создание моего собственного объекта события перетаскивания (общий интерфейс для событий мыши и касания), который содержит координаты события и цель:
- для событий мыши я просто повторно использую событие мыши, как
-
для сенсорного события, которое я использую:
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()
, похоже, поддерживает значение pointer-events
даже на Android.