Reputation: 1110
I'm building a paint-like feature where the user can draw a line, but the touchmove event gets emitted really slow on my device (android phone), so the line becomes edgy. As soon as I connect the device to my PC and open the chrome devtools via USB debugging, everything works fine. On the phone emulator in desktop-chrome aren't any problems.
Here is a screenshot. The inner circle was drawn with the slow touch events, and for the outer one I connected the device to my PC.
Here is another screenshot showing the durations between individual "touchmove" event-calls. The top part (green values) occured when the devtools were open, the bottom part (red values) when they were closed.
The code:
function DrawingCanvas(/* ... */) {
// ...
const handleTouchMove = (event) => {
handleMouseMove(event.touches[0])
}
const handleMouseMove = ({ clientX, clientY }) => {
if (!isDrawing) {
return
}
const canvasRect = canvas.getBoundingClientRect()
const x = clientX - canvasRect.x
const y = clientY - canvasRect.y
currentPath.current.addPoint([x, y])
update()
}
const update = () => {
clearCanvas()
drawPath()
}
// ...
useEffect(() => {
const drawingCanvas = drawingCanvasRef.current
// ...
drawingCanvas.addEventListener("touchstart", handleDrawStart)
drawingCanvas.addEventListener("touchend", handleDrawEnd)
drawingCanvas.addEventListener("touchcancel", handleDrawEnd)
drawingCanvas.addEventListener("touchmove", handleTouchMove)
drawingCanvas.addEventListener("mousedown", handleDrawStart)
drawingCanvas.addEventListener("mouseup", handleDrawEnd)
drawingCanvas.addEventListener("mousemove", handleMouseMove)
return () => {
drawingCanvas.removeEventListener("touchstart", handleDrawStart)
drawingCanvas.removeEventListener("touchmove", handleTouchMove)
drawingCanvas.removeEventListener("touchend", handleDrawEnd)
drawingCanvas.removeEventListener("touchcancel", handleDrawEnd)
drawingCanvas.removeEventListener("mousedown", handleDrawStart)
drawingCanvas.removeEventListener("mouseup", handleDrawEnd)
drawingCanvas.removeEventListener("mousemove", handleMouseMove)
}
})
return <canvas /* ... */ />
}
Does anyone have an idea on how to fix this?
You can test it by yourself on the website: https://www.easymeme69.com/editor
Upvotes: 4
Views: 2917
Reputation: 11
I've had the same problem. I had no freezes on mobile or firefox, only on Chromium. Either disabling touchpad-overscroll-history-navigation in chrome-flags or e.preventDefault()
can solve the problem.
Upvotes: 1
Reputation: 502
I'm facing exactly the same situation, I'm developing a React app with some touch features implementing actions on touchmove
.
All my tests are done inside Chrome on the Debian-based Raspberry OS distro.
It results in a deadly laggy UI with a real touch screen...except (this is when it becomes very interesting!) if the console is opened with Chrome mobile emulator, then even if I try to play with my finger on the real touch screen at this moment.
touch-action: none
& event.stopPropagation
hacks were already existing in my code and didn't change the game.
2 conclusions on that :
As for now, the mystery is still opaque for me.
My feeling is that, somehow, Chrome is deliberately decreasing/increasing the touch events rate depending (correspondingly) on whether we're in a real use case or whether we're on the emulator. I created a simple fiddle to validate this hypothesis: https://jsfiddle.net/ncgtjesh/20/show
It seems to be the case since I can clearly that the emulator-enabled mode outputs 240 events/second while the real non-emulated interface is stuck to 120.
I'm quite surprised that the fixes enacted in the responses above made it since it seems to be a browser implementation choice.
Upvotes: 3
Reputation: 83
I had this exact same thing happen to me, down to not being able to reproduce with USB debugging open. Besides the e.preventDefault()
hack, you can also set the touchable element's touch-action: none;
in CSS.
Upvotes: 3
Reputation: 1110
Somehow calling event.preventDefault()
on the touchmove event fixed it.
Upvotes: 7