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

解决HTML Canvas尺寸放大后绘制位置与鼠标偏移的问题

Canvas绘制位置与鼠标点击偏差的解决方法

问题根源在于Canvas存在两个独立的尺寸:

  • 绘图缓冲区尺寸:由canvas元素的width和height属性控制,这是Canvas实际用来绘制图形的像素尺寸,默认是300x150。
  • 显示尺寸:由CSS的width和height控制,只是把缓冲区的像素拉伸/压缩到页面上的显示大小。

你只通过CSS设置了全屏显示,但绘图缓冲区还是默认尺寸,导致鼠标坐标和绘图坐标的比例不匹配,出现偏差。

解决步骤:

  1. 同步绘图缓冲区与显示尺寸:初始化时将canvas的width和height属性设置为窗口的实际像素大小,确保缓冲区和显示区域像素一一对应。
  2. 处理窗口 resize 事件:当窗口大小改变时,重新更新缓冲区尺寸,避免拉伸变形。
  3. 修正鼠标坐标转换:将鼠标的客户端坐标转换为Canvas的绘图坐标,确保点击位置和绘制位置完全匹配。

修正后的完整代码:

CSS(保持原有样式)

@import "compass/css3";

html, body {
  width: 100%;
  height: 100%;
  margin: 0px;
  overflow: hidden;
  
    &:hover {
   span {
      display: none; 
    }
  }
}

canvas {
 cursor: crosshair;
 border: 1px solid red;
 width: 100vw;
 height: 100vh;
}

span {
  font-family: 'Georgia', cursive;
  font-size: 40px;
  position: fixed; 
  top: 50%;
  left: 50%;
  color: #000;
  margin-top: -40px;
  margin-left: -200px;
}

HTML(无需改动)

<canvas id='canvas'></canvas>

JavaScript(核心修改部分)

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');

let isDrawing = false;
let lastX = 0;
let lastY = 0;

// 初始化并同步Canvas尺寸
function resizeCanvas() {
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;
}

// 将鼠标坐标转换为Canvas绘图坐标
function getCanvasCoords(e) {
  const rect = canvas.getBoundingClientRect();
  return {
    x: e.clientX - rect.left,
    y: e.clientY - rect.top
  };
}

resizeCanvas();
window.addEventListener('resize', resizeCanvas);

canvas.addEventListener('mousedown', (e) => {
  isDrawing = true;
  const coords = getCanvasCoords(e);
  [lastX, lastY] = [coords.x, coords.y];
});

canvas.addEventListener('mousemove', (e) => {
  if (!isDrawing) return;
  const coords = getCanvasCoords(e);
  ctx.beginPath();
  ctx.moveTo(lastX, lastY);
  ctx.lineTo(coords.x, coords.y);
  ctx.strokeStyle = 'black';
  ctx.lineWidth = 2;
  ctx.stroke();
  [lastX, lastY] = [coords.x, coords.y];
});

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

关键改动说明:

  • 新增resizeCanvas函数,同步canvas的width/height属性与窗口尺寸,确保绘图缓冲区和显示区域一致。
  • 新增getCanvasCoords函数,通过getBoundingClientRect()获取Canvas在页面中的位置,将鼠标的clientX/clientY转换为Canvas内部的绘图坐标,避免因CSS拉伸导致的坐标偏差。
  • 监听窗口resize事件,窗口大小变化时重新调整Canvas尺寸,保持绘图精度。

内容的提问来源于stack exchange,提问作者Alberto De Maria

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 05:05:19