You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

移动端Canvas使用pointermove事件时pointerleave异常触发问题

问题解决:安卓端Pointer事件Canvas绘图异常(触发pointerleave中断)

问题现象

使用Pointer事件实现Canvas绘图,桌面端鼠标操作可正常绘制连续曲线,但安卓手机上手指拖动时,仅触发pointerenter和少量pointermove事件后就会触发pointerleave,导致绘图中断。

问题根源

  1. 移动端触摸操作默认会触发浏览器的滚动、缩放等手势,这些行为会抢占事件焦点,导致Pointer事件中断并触发pointerleave。
  2. 初始坐标变量xx、yy未初始化,第一次pointermove时xold、yold为undefined,绘制逻辑异常。
  3. 缺少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>

关键修改解释

  1. touch-action: none:CSS样式直接禁用Canvas区域的浏览器触摸手势,避免滚动、缩放等行为干扰Pointer事件。
  2. pointerdown事件处理:在触摸开始时记录初始坐标,同时调用ev.preventDefault()阻止默认行为,确保触摸操作的事件焦点持续在Canvas上。
  3. ev.buttons !== 1判断:确保只有在触摸按下(或鼠标按下)状态下才执行绘制逻辑,避免误触发。
  4. 坐标初始化:在pointerdown中初始化xx、yy,解决第一次绘制时起始坐标未定义的问题。

内容的提问来源于stack exchange,提问作者dcromley

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 10:50:37