touchmove 事件在替换 innerHTML 后停止
touchmove events stop after replacing innerHTML
我有一个网页跟踪 touchmove 事件,允许用户在屏幕上拖动元素 - 工作正常。
我 在用户移动时动态替换移动元素中的 html - 替换 html 工作正常。
问题是如果用户通过触摸内部html(它被替换)拖动,那么一旦内部[=61]拖动(touchmove事件)停止=] 被替换(直到下一次触摸开始)。
事件侦听器在外部容器上,而不是被替换的 html,所以我认为它应该继续捕获事件。
mousemove 事件也不会出现此问题。
我做了一个jsfiddle demo。使用鼠标应该可以正常工作,不会出现任何问题(mousemove 事件)。当您使用触摸设备(或使用 Chrome 的触摸模拟:更多工具 > 传感器 > 触摸 > 强制启用)时会出现此问题。
https://jsfiddle.net/dmdjvd7e/1/
相同但使用 jquery:https://jsfiddle.net/a2fwkr4e/6/
在演示中,您可以在屏幕周围拖动红色圆圈。
圆圈内的黄色框每秒更换一次。
如果你触摸红色(而不是黄色),那么一切都会正常工作。
如果你触摸黄色,那么事情会一直有效,直到黄色框被替换(每秒),之后你不会移动元素,直到你再次触摸开始。
这是预期的浏览器行为吗?为什么 mousemove 不同?
有没有办法解决这个问题,同时仍然允许我替换 html?
如果我不替换内部 html,而只是修改它或简单地替换文本而不是 html 元素,那么就没有问题。但是,我希望能够替换 html(根据现有应用程序要求)。
...
为了完整性而包含的代码(与 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;
}
使用 Chrome 62 和 Firefox 56(均在 Windows 10)和 Chrome 60(Android N)以及Safari/webkit602.1 (iPhone6).
嗯..我想我应该阅读规范:
"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
此外,在输入所有内容后,我发现已经有人问过同样的问题并且有几个答案:
我有一个网页跟踪 touchmove 事件,允许用户在屏幕上拖动元素 - 工作正常。
我 在用户移动时动态替换移动元素中的 html - 替换 html 工作正常。
问题是如果用户通过触摸内部html(它被替换)拖动,那么一旦内部[=61]拖动(touchmove事件)停止=] 被替换(直到下一次触摸开始)。
事件侦听器在外部容器上,而不是被替换的 html,所以我认为它应该继续捕获事件。
mousemove 事件也不会出现此问题。
我做了一个jsfiddle demo。使用鼠标应该可以正常工作,不会出现任何问题(mousemove 事件)。当您使用触摸设备(或使用 Chrome 的触摸模拟:更多工具 > 传感器 > 触摸 > 强制启用)时会出现此问题。
https://jsfiddle.net/dmdjvd7e/1/
相同但使用 jquery:https://jsfiddle.net/a2fwkr4e/6/
在演示中,您可以在屏幕周围拖动红色圆圈。 圆圈内的黄色框每秒更换一次。 如果你触摸红色(而不是黄色),那么一切都会正常工作。 如果你触摸黄色,那么事情会一直有效,直到黄色框被替换(每秒),之后你不会移动元素,直到你再次触摸开始。
这是预期的浏览器行为吗?为什么 mousemove 不同? 有没有办法解决这个问题,同时仍然允许我替换 html?
如果我不替换内部 html,而只是修改它或简单地替换文本而不是 html 元素,那么就没有问题。但是,我希望能够替换 html(根据现有应用程序要求)。
...
为了完整性而包含的代码(与 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;
}
使用 Chrome 62 和 Firefox 56(均在 Windows 10)和 Chrome 60(Android N)以及Safari/webkit602.1 (iPhone6).
嗯..我想我应该阅读规范:
"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
此外,在输入所有内容后,我发现已经有人问过同样的问题并且有几个答案: