Touch Move event don't fire after Touch Start target is removed

試著忘記壹切 提交于 2019-11-29 13:53:28

Indeed, according to the docs,

If the target element is removed from the document, events will still be targeted at it, and hence won't necessarily bubble up to the window or document anymore. If there is any risk of an element being removed while it is being touched, the best practice is to attach the touch listeners directly to the target.

It turns out that the solution is to attach touchmove and touchend listeners to the event.target itself, for example:

element.addEventListener("touchstart", (event) => {
    const onTouchMove = () => {
        // handle touchmove here
    }
    const onTouchEnd = () => {
        event.target.removeEventListener("touchmove", onTouchMove);
        event.target.removeEventListener("touchend", onTouchEnd);
        // handle touchend here
    }
    event.target.addEventListener("touchmove", onTouchMove);
    event.target.addEventListener("touchend", onTouchEnd);
    // handle touchstart here
});

Even if the event.target element is removed from the DOM, events will continue to fire normally and give correct coordinates.

The trick is to hide element until touch move finishes, but not to remove it. Here is some example (enable Touch Mode in Chrome Dev Tools and select some device or use real device): https://jsfiddle.net/alexanderby/na3rumjg/

var marker = document.querySelector('circle');
var onStart = function(startEvt) {
  startEvt.preventDefault(); // Prevent scroll
  marker.style.visibility = 'hidden'; // Hide target element
  var rect = document.querySelector('rect');
  var initial = {
    x: +rect.getAttribute('x'),
    y: +rect.getAttribute('y')
  };
  var onMove = function(moveEvt) {
    rect.setAttribute('x', initial.x + moveEvt.touches[0].clientX - startEvt.touches[0].clientX);
    rect.setAttribute('y', initial.y + moveEvt.touches[0].clientY - startEvt.touches[0].clientY);
  };
  var onEnd = function(endEvt) {
    window.removeEventListener('touchmove', onMove);
    window.removeEventListener('touchend', onEnd);
    marker.removeEventListener('touchstart', onStart);
    marker.parentElement.removeChild(marker); // Remove target element
  };
  window.addEventListener('touchmove', onMove);
  window.addEventListener('touchend', onEnd);
};
marker.addEventListener('touchstart', onStart);
<svg>
  <circle r="20" cx="50" cy="20" cursor="move"/>
  <rect x="10" y="50" width="80" height="80" />
</svg>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!