问题
I have a webpage that tracks touchmove events allowing the user to drag an element around the screen - works fine.
I dynamically replace html within the moving element while the user is moving it - replacing html works fine.
The issue is if the user drags by touching the inner html (which gets replaced) then the dragging (touchmove events) stop once that inner html is replaced (until the next touchstart).
The event listener is on an outside container, NOT the html that is replaced, so I would think it should keep capturing the events.
Also this issue does NOT occur with mousemove events.
I have made a jsfiddle demo. Using your mouse should work fine and no issues will occur (mousemove events). The issue will arise when you use a touch device (or use Chrome's touch simulation: More Tools > Sensors > Touch > Force Enabled).
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).
回答1:
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
来源:https://stackoverflow.com/questions/46328747/touchmove-events-stop-after-replacing-innerhtml