替换innerHTML后,touchmove事件停止 [英] touchmove events stop after replacing innerHTML

查看:93
本文介绍了替换innerHTML后,touchmove事件停止的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个网页跟踪 touchmove 事件,允许用户在屏幕上拖动元素-工作正常.

在用户移动移动元素时动态替换html -替换html效果很好.

问题是,如果用户通过触摸内部html进行拖动(将替换掉),然后一旦替换了内部html(直到下一次touchstart),拖动(touchmove事件)就会停止.>

事件侦听器位于外部容器上,而不是替换的html上,因此我认为它应该继续捕获事件.

mousemove 事件也不会发生此问题.

我做了一个jsfiddle演示.使用鼠标应该可以正常工作,并且不会发生任何问题(ousemove事件).当您使用触摸设备(或使用Chrome的触摸模拟:更多工具>传感器>触摸>强制启用)时,就会出现此问题.

https://jsfiddle.net/dmdjvd7e/1/

相同但使用jquery: https://jsfiddle.net/a2fwkr4e/6/

在演示中,您可以在屏幕周围拖动红色圆圈.圆圈中的黄色框每秒被替换一次.如果您触摸红色(而不是黄色),则说明一切正常.如果您触摸黄色,则一切正常,直到替换黄色框(每秒),之后您才可以移动元素,直到再次触摸开始.

这是预期的浏览器行为吗?为什么mousemove与众不同?在仍然允许我替换html的同时,有没有办法解决此问题?

如果我不替换内部html,而是对其进行修改,或者仅替换文本而不是html元素,那么就没有问题.但是,我希望能够替换html(根据现有的应用程序要求).

...

包含完整性的代码(与jsfiddle相同):

css/html:

 < style>.容器 {用户选择:无;背景颜色:灰色;位置:绝对;顶:0;左:0;底部:0;对:0;}.dot {边界半径:100%;背景颜色:红色;padding:2em;裕度:-4em 0 0 -4em;位置:绝对;顶部:3em;左:3em;颜色:蓝色;}.dot div {font-weight:粗体;颜色:黑色;背景颜色:黄色;padding:2em;}</style>< div class ='container'>< div class ='dot'>< div class ='num'> 0lt//div></div></div> 

js:

  var eContainer = document.querySelector('.container'),eDot = document.querySelector('.dot'),dragActive = false,val = 0;var hInterval = setInterval(function(){++ val;eDot.innerHTML ='< div class ="num">'+ val +'</div>';},1000);eContainer.addEventListener('touchstart',dragStart);eContainer.addEventListener('touchend',dragEnd);eContainer.addEventListener('touchmove',dragMove);eContainer.addEventListener('mousedown',dragStart);eContainer.addEventListener('click',dragEnd);eContainer.addEventListener('mousemove',dragMove);函数dragStart(e){dragActive = true;}函数dragMove(e){如果(!dragActive)返回;var posX = e.clientX ||(e.touches&& e.touches.length?e.touches [0] .pageX:0),posY = e.clientY ||(e.touches&& e.touches.length?e.touches [0] .pageY:0);eDot.style.left = posX +'px';eDot.style.top = posY +'px';}函数dragEnd(e){dragActive = false;} 

已通过Chrome 62&Firefox 56(均在Windows 10上)&Chrome 60(Android N)以及Safari/webkit 602.1(iPhone 6).

解决方案

好吧.我想我应该读懂规范:

此事件的目标必须与接触点首次放置在表面上时在其上开始的元素相同,即使此后接触点已移出目标元素的交互区域之外."

https://www.w3.org/TR/touch-events/#the-touchmove-event

此外,在完成所有键入操作之后,我发现已经问过相同的问题,并且有几个答案:https://jsfiddle.net/dmdjvd7e/1/

Same but using jquery: https://jsfiddle.net/a2fwkr4e/6/

In the demo you can drag the red circle around the screen. The yellow box within the circle is replaced every second. If you touch the red (not the yellow) then things will work correctly. If you touch the yellow then things will work until the yellow box is replaced (each second), after-which you wont be moving the element until you touchstart again.

Is this intended browser behaviour? why is mousemove different? Is there a way around this while still allowing me to replace html?

If I don't replace the inner html, and instead just modify it or simply replace the text and not the html elements then there are no problems. However, I'd like to be able to replace the html (as per existing application requirements).

...

Code included for completeness (same as jsfiddle):

css/html:

<style>
.container {
  user-select: none;
  background-color: gray;
  position: absolute;
  top:0;
  left:0;
  bottom:0;
  right:0;
}

.dot {
  border-radius: 100%;
  background-color: red;
  padding: 2em;
  margin: -4em 0 0 -4em;
  position: absolute;
  top: 3em;
  left: 3em;
  color: blue;
}
.dot div {
  font-weight: bold;
  color: black;
  background-color: yellow;
  padding: 2em;
}
</style>
<div class='container'>
  <div class='dot'><div class='num'>0</div></div>
</div>

js:

var eContainer = document.querySelector('.container'),
eDot = document.querySelector('.dot'),
dragActive = false,
val = 0;

var hInterval = setInterval(function() {
    ++val;
    eDot.innerHTML = '<div class="num">' + val + '</div>';
}, 1000);

eContainer.addEventListener('touchstart', dragStart);
eContainer.addEventListener('touchend', dragEnd);
eContainer.addEventListener('touchmove', dragMove);

eContainer.addEventListener('mousedown', dragStart);
eContainer.addEventListener('click', dragEnd);
eContainer.addEventListener('mousemove', dragMove);

function dragStart(e) {
    dragActive = true;
}

function dragMove(e) {
    if (!dragActive) return;

  var posX = e.clientX || (e.touches && e.touches.length ? e.touches[0].pageX : 0),
        posY = e.clientY || (e.touches && e.touches.length ? e.touches[0].pageY : 0);

  eDot.style.left = posX + 'px';
  eDot.style.top = posY + 'px';
}

function dragEnd(e) {
    dragActive = false;
}

Tested with Chrome 62 & Firefox 56 (both on Windows 10) & Chrome 60 (Android N), as well as Safari/webkit 602.1 (iPhone 6).

解决方案

Well.. I suppose I should have read the spec:

"The target of this event must be the same Element on which the touch point started when it was first placed on the surface, even if the touch point has since moved outside the interactive area of the target element."

https://www.w3.org/TR/touch-events/#the-touchmove-event

Also, after all that typing, I've found the same question was already asked and has a couple answers: Touch Move event don't fire after Touch Start target is removed

这篇关于替换innerHTML后,touchmove事件停止的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆