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

CSS旋转90deg后Canvas strokeRect鼠标坐标偏移问题求助

解决Canvas CSS旋转后鼠标绘图坐标错位问题

问题本质

CSS的transform: rotate(90deg)仅对Canvas元素做视觉层面的旋转,Canvas自身的绘图坐标系(原点在左上角,x轴向右、y轴向下)并未改变。但鼠标事件的clientX/clientY是基于浏览器窗口的坐标,直接映射到Canvas原坐标系就会出现错位。

核心解决方案:坐标矩阵转换

利用Canvas的getScreenCTM()获取包含CSS变换的矩阵,再通过逆矩阵将鼠标坐标转换为Canvas本地坐标系的正确位置:

坐标转换函数

function getCanvasLocalPos(canvas, clientX, clientY) {
  const rect = canvas.getBoundingClientRect();
  // 获取变换矩阵的逆矩阵,用于将屏幕坐标转回Canvas本地坐标
  const inverseMatrix = canvas.getScreenCTM().inverse();
  // 创建鼠标相对于Canvas元素的坐标点
  const mousePoint = new DOMPoint(clientX - rect.left, clientY - rect.top);
  // 应用逆矩阵转换
  const localPoint = mousePoint.matrixTransform(inverseMatrix);
  return { x: localPoint.x, y: localPoint.y };
}

在鼠标事件中使用

在mousedown、mousemove等事件里,替换原来的坐标计算逻辑:

canvas.addEventListener('mousedown', (e) => {
  const { x, y } = getCanvasLocalPos(canvas, e.clientX, e.clientY);
  // 用转换后的x、y作为矩形起始点
  startX = x;
  startY = y;
});

替代方案:使用Canvas自身坐标系旋转

如果不想用CSS变换,直接操作Canvas上下文的坐标系:

  1. 调整Canvas宽高(旋转90度后宽高互换)
  2. 重设上下文变换:
const ctx = canvas.getContext('2d');
// 保存原状态
ctx.save();
// 平移到画布中心
ctx.translate(canvas.width / 2, canvas.height / 2);
// 旋转90度(Math.PI/2 对应90度)
ctx.rotate(Math.PI / 2);
// 平移回原点,确保绘图原点对齐视觉左上角
ctx.translate(-canvas.height / 2, -canvas.width / 2);
// 此时绘图会自动应用旋转,鼠标坐标也需要对应转换:
// 旋转90度后,原(x,y)对应新坐标为 (canvas.height - y, x)
ctx.restore(); // 结束后可恢复原状态

关键注意事项

  • 避免混用CSS变换和Canvas上下文变换,两种方式的坐标转换逻辑完全不同
  • getBoundingClientRect()返回的是旋转后的元素可视尺寸,而Canvas的width/height属性是绘图缓冲区的原始尺寸,两者不能混淆

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 21:12:42