触摸移动事件在触发启动目标移除后不会触发

时间:2015-10-23 09:17:57

标签: javascript google-chrome events touch pointer-events

我尝试使用下一个模式实现类似拖拽的功能:

  • 订阅marker指针向下事件。
  • 当Down事件触发时,订阅Window Pointer Move和Up事件并删除标记。
  • 移动时执行某些操作。
  • 当Up事件触发取消订阅Move and Up时。

这适用于鼠标事件,但不适用于Touch事件。删除Touch Start目标元素后,它们不会触发。我尝试使用query,但它也没有用。

我使用Chrome开发工具来模拟触摸事件。见样本:



.parent {
  background: darkred;
  color: white;
  width: 10em;
  height: 10em;
  position: absolute;
}
.target {
  background: orange;
  width: 4em;
  height: 4em;
}
#mouse .parent {
  left: 0em;
}
#touch .parent {
  left: 11em;
}
#touch-no-remove .parent {
  left: 22em;
}

<div id="mouse">
  <div class="parent">Mouse events
    <div class="target">Drag here</div>
  </div>
</div>
<div id="touch">
  <div class="parent">Touch events
    <div class="target">Drag here</div>
  </div>
</div>
<div id="touch-no-remove">
  <div class="parent">Touch (no remove)
    <div class="target">Drag here</div>
  </div>
</div>
&#13;
a
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:8)

确实,according to the docs

  

如果从文档中删除目标元素,事件仍将是   瞄准它,因此不一定会冒泡到窗口   或文件了。如果有任何元素被删除的风险   当它被触摸时,最好的做法是附加触摸   听众直接指向目标。

事实证明,解决方案是将touchmovetouchend个侦听器附加到event.target本身,例如:

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
});

即使从DOM中删除了event.target元素,事件也会继续正常触发并提供正确的坐标。

答案 1 :(得分:2)

诀窍是隐藏元素,直到触摸移动完成,但不删除它。 以下是一些示例(在Chrome开发者工具中启用触摸模式并选择一些设备或使用真实设备): 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>