移动端Canvas使用pointermove事件时pointerleave异常触发问题
问题解决:安卓端Pointer事件Canvas绘图异常(触发pointerleave中断)
问题现象
使用Pointer事件实现Canvas绘图,桌面端鼠标操作可正常绘制连续曲线,但安卓手机上手指拖动时,仅触发pointerenter和少量pointermove事件后就会触发pointerleave,导致绘图中断。
问题根源
- 移动端触摸操作默认会触发浏览器的滚动、缩放等手势,这些行为会抢占事件焦点,导致Pointer事件中断并触发
pointerleave。 - 初始坐标变量
xx、yy未初始化,第一次pointermove时xold、yold为undefined,绘制逻辑异常。 - 缺少
pointerdown事件处理,无法在触摸开始时锁定交互焦点并阻止默认行为。
修复方案
修改点说明
- 添加
pointerdown事件监听,触摸开始时记录初始坐标,并调用ev.preventDefault()阻止浏览器默认触摸行为,避免手势干扰。 - 初始化
xx、yy变量,确保第一次绘制有合法的起始坐标。 - 给Canvas添加
touch-action: none样式,明确禁用浏览器触摸手势,进一步稳定事件触发。
修复后的完整代码
<!DOCTYPE html> <html> <!-- 修复后支持桌面和安卓端绘图 --> <head> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> body { width:400px; } #canvas { background:#eee; touch-action: none; /* 禁用浏览器触摸手势 */ } </style> <script> "use strict"; let canvas, ctx, xx, yy, infodiv; window.onload = function() { infodiv = document.getElementById("infodiv"); canvas = document.getElementById("canvas"); ctx = canvas.getContext("2d"); canvas.addEventListener('pointerenter', ptrEnter); canvas.addEventListener('pointerleave', ptrLeave); canvas.addEventListener('pointerdown', ptrDown); // 添加触摸开始事件 canvas.addEventListener('pointermove', ptrMove); } function ptrEnter() { infodiv.innerHTML += "ENTER "; } function ptrLeave() { infodiv.innerHTML += "LEAVE "; } function ptrDown(ev) { infodiv.innerHTML += "DOWN "; // 阻止浏览器默认触摸行为(滚动、缩放等) ev.preventDefault(); // 记录触摸起始坐标 let x0 = canvas.offsetLeft, y0 = canvas.offsetTop; xx = Math.floor(ev.clientX) - x0; yy = Math.floor(ev.clientY) - y0; } function ptrMove(ev) { // 只有在触摸按下状态才绘制 if (ev.buttons !== 1) return; infodiv.innerHTML += "m "; let x0 = canvas.offsetLeft, y0 = canvas.offsetTop; let xold = xx, yold = yy; xx = Math.floor(ev.clientX) - x0; yy = Math.floor(ev.clientY) - y0; ctx.beginPath(); ctx.moveTo(xold,yold); ctx.lineTo(xx, yy); ctx.stroke(); } </script> </head> <body> <canvas id="canvas" width="400" height="300"></canvas> <div id="infodiv">Events: </div> </body> </html>
关键修改解释
touch-action: none:CSS样式直接禁用Canvas区域的浏览器触摸手势,避免滚动、缩放等行为干扰Pointer事件。pointerdown事件处理:在触摸开始时记录初始坐标,同时调用ev.preventDefault()阻止默认行为,确保触摸操作的事件焦点持续在Canvas上。ev.buttons !== 1判断:确保只有在触摸按下(或鼠标按下)状态下才执行绘制逻辑,避免误触发。- 坐标初始化:在
pointerdown中初始化xx、yy,解决第一次绘制时起始坐标未定义的问题。
内容的提问来源于stack exchange,提问作者dcromley
相关产品推荐
相关产品推荐

