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

Canvas签名绘制线条偏移问题:线条未匹配鼠标位置

Canvas签名绘制鼠标偏移问题解决

这个问题的核心原因是Canvas的绘图缓冲区尺寸(标签上的width/height属性)和页面显示尺寸(CSS设置的尺寸)不匹配,导致鼠标坐标和绘图坐标的映射错位。

解决方法

方法1:统一Canvas的属性尺寸和CSS尺寸

直接让Canvas的CSS样式尺寸和标签上的width/height属性值一致,这样鼠标的offsetX/offsetY就能直接对应绘图坐标:

添加CSS样式:

#signature-pad {
  width: 400px;
  height: 200px;
  border: 1px solid #ccc; /* 可选,方便识别画布范围 */
}

你的HTML和JS代码不需要修改,保持原样即可。

方法2:动态转换坐标(适合响应式场景)

如果需要Canvas自适应容器大小(比如随窗口缩放),不能固定尺寸,就需要计算显示尺寸和原生尺寸的比例,把鼠标坐标转换成Canvas的绘图坐标:

修改JS代码如下:

// Select the canvas element
const canvas = document.getElementById('signature-pad');
const ctx = canvas.getContext('2d');

// Set up event listeners
let isDrawing = false;
let lastX = 0;
let lastY = 0;

// 计算Canvas显示尺寸和原生尺寸的比例
function getCanvasScale() {
  const rect = canvas.getBoundingClientRect();
  return {
    scaleX: canvas.width / rect.width,
    scaleY: canvas.height / rect.height
  };
}

canvas.addEventListener('mousedown', e => {
  isDrawing = true;
  const { scaleX, scaleY } = getCanvasScale();
  lastX = e.offsetX * scaleX;
  lastY = e.offsetY * scaleY;
});

canvas.addEventListener('mousemove', e => {
  if (isDrawing) {
    const { scaleX, scaleY } = getCanvasScale();
    const currentX = e.offsetX * scaleX;
    const currentY = e.offsetY * scaleY;
    
    ctx.beginPath();
    ctx.moveTo(lastX, lastY);
    ctx.lineTo(currentX, currentY);
    ctx.stroke();
    
    lastX = currentX;
    lastY = currentY;
  }
});

canvas.addEventListener('mouseup', () => {
  isDrawing = false;
});

canvas.addEventListener('mouseout', () => {
  isDrawing = false;
});

// Set up button event listeners
const clearButton = document.getElementById('clear-button');
clearButton.addEventListener('click', () => {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
});

const saveButton = document.getElementById('save-button');
saveButton.addEventListener('click', () => {
  const dataURL = canvas.toDataURL();
  console.log(dataURL);
});

原理说明

Canvas有两个独立的尺寸:

  1. 绘图缓冲区尺寸:由标签上的width和height属性决定,是Canvas内部用于绘制的像素网格大小。
  2. 页面显示尺寸:由CSS样式决定,是Canvas元素在页面上占据的空间大小。

如果这两个尺寸不一致,浏览器会自动拉伸或压缩绘图缓冲区来适配显示尺寸,此时鼠标的offsetX/offsetY是基于显示尺寸的坐标,直接用于绘图就会出现偏移。通过统一尺寸或坐标转换,就能让绘制的线条和鼠标位置对齐。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 02:06:25