Подтвердить что ты не робот

Как узнать реальную 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.

Вопрос: есть ли способ определить фактический элемент под пальцем (НЕ изначально затронутый элемент, который может быть другим во многих случаях)?

4b9b3361

Ответ 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 на рабочем столе с сенсорным экраном

Не тестировалось:

  • Windows Phone

Ответ 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.