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

HTML Canvas绑定触摸事件后绘制线条不显示该如何解决?

问题根因

触摸事件对象没有鼠标事件独有的offsetX、offsetY属性,你当前直接读取这两个值会得到undefined,导致绘制坐标异常,线条落在画布可视范围外。

修复步骤

  • 调整触摸事件的坐标计算逻辑:从触摸点列表event.touches[0]中获取相对于视口的坐标clientX、clientY,再减去canvas元素距视口的偏移量,得到canvas内部的相对坐标。
  • 可补充touchcancel事件监听,对应触摸操作被系统中断(比如突然收到来电)的场景,和mouseout作用类似。
  • 可选在触摸事件中添加event.preventDefault()避免低版本浏览器偶发的默认滚动行为干扰,你已经设置了touch-action: none,现代浏览器场景下可省略。

修复后的触摸适配代码

// 平板触控适配逻辑
let isTouchDown = false;
// 新增方法获取canvas相对于视口的偏移量,用于坐标换算
const getCanvasOffset = () => {
  const rect = paintCanvas.getBoundingClientRect();
  return { left: rect.left, top: rect.top };
}

const stopDrawingTouch = () => {
  isTouchDown = false;
}
const startDrawingTouch = event => {
  event.preventDefault();
  isTouchDown = true;
  const offset = getCanvasOffset();
  // 取第一个触摸点的视口坐标,减去canvas偏移得到画布内坐标
  [x, y] = [event.touches[0].clientX - offset.left, event.touches[0].clientY - offset.top];
}
const drawLineTouch = event => {
  event.preventDefault();
  if ( isTouchDown ) {
    const offset = getCanvasOffset();
    const newX = event.touches[0].clientX - offset.left;
    const newY = event.touches[0].clientY - offset.top;
    context.beginPath();
    context.moveTo( x, y );
    context.lineTo( newX, newY );
    context.stroke();
    x = newX;
    y = newY;
  }
}

paintCanvas.addEventListener( 'touchstart', startDrawingTouch );
paintCanvas.addEventListener( 'touchmove', drawLineTouch );
paintCanvas.addEventListener( 'touchend', stopDrawingTouch );
// 补充触摸中断事件处理
paintCanvas.addEventListener( 'touchcancel', stopDrawingTouch );

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 19:24:06