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

如何在使用object-fit: contain时将鼠标位置转换为画布坐标

解决object-fit: contain下画布鼠标坐标偏差问题

使用object-fit: contain可以调整画布大小以适配容器,但当前代码中通过鼠标事件绘制圆形时,仅在画布中间位置能和指针匹配,其他位置会出现偏差——这是因为鼠标事件的坐标覆盖了包含黑边(留白)的整个canvas元素区域,直接按元素宽高比例转换坐标的逻辑忽略了contain带来的留白偏移。

问题根源

object-fit: contain会让画布保持原始宽高比缩放到容器内,当容器比例和画布原始比例不一致时,某一方向会出现留白(黑边)。但offsetX/offsetY是相对于canvas元素的整体尺寸(含留白),直接用e.offsetX * canvas.width / canvas.offsetWidth计算会把留白区域的坐标也算进去,导致偏移。

解决方案:计算有效区域的偏移和缩放比例

需要先算出画布实际显示内容在canvas元素内的位置(留白的偏移量)和缩放比例,再将鼠标坐标转换为画布原始坐标:

修改后的完整代码

<div id="container">
  <canvas id="canvas"></canvas>
</div>
<div id="pt"></div>
#container {
  height: 150px;
}
#canvas {
  object-fit: contain;
  width: 100%;
  height: 100%;
  border: 1px solid red;
}
const canvas = document.getElementById('canvas');
const pt = document.getElementById('pt');
// 画布原始尺寸
canvas.width = 1920;
canvas.height = 1200;
const ctx = canvas.getContext('2d');
ctx.lineWidth = 10;
ctx.strokeRect(0, 0, canvas.width, canvas.height);

canvas.onmousemove = (e) => {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.strokeRect(0, 0, canvas.width, canvas.height);
  
  // 计算画布元素的显示尺寸和原始尺寸的比例
  const canvasRatio = canvas.width / canvas.height;
  const elementRatio = e.target.offsetWidth / e.target.offsetHeight;
  
  let scale, offsetX, offsetY;
  if (elementRatio > canvasRatio) {
    // 容器更宽,上下留白
    scale = e.target.offsetHeight / canvas.height;
    offsetX = (e.target.offsetWidth - canvas.width * scale) / 2;
    offsetY = 0;
  } else {
    // 容器更高,左右留白
    scale = e.target.offsetWidth / canvas.width;
    offsetX = 0;
    offsetY = (e.target.offsetHeight - canvas.height * scale) / 2;
  }
  
  // 转换鼠标坐标到画布原始坐标
  const x = Math.round((e.offsetX - offsetX) / scale);
  const y = Math.round((e.offsetY - offsetY) / scale);
  
  ctx.beginPath();
  ctx.arc(x, y, 10, 0, 2 * Math.PI);
  ctx.stroke();
  pt.innerText = `${x}x${y}`;
};

逻辑说明

  1. 计算比例:对比画布原始宽高比和canvas元素的显示宽高比,判断是上下留白还是左右留白
  2. 计算缩放比例:根据匹配的方向(宽或高)算出实际的缩放倍数
  3. 计算偏移量:算出留白区域的宽度/高度,得到有效绘制区域的起始坐标
  4. 转换坐标:用鼠标的offsetX/offsetY减去留白偏移,再除以缩放比例,得到画布原始尺寸下的坐标

这样就能确保鼠标指针和绘制的圆形在任何位置都精准匹配,同时保留object-fit: contain的适配效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 06:27:38