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

Canvas嵌套Dialog触摸绘图位置偏移问题求助

解决Dialog中Canvas触摸绘图位置偏移问题

你当前计算触摸点偏移的方式完全错误——用screen.width/screen.height凑偏移量还硬减25,根本没考虑Dialog和Canvas在视口中的实际位置。正确的做法是获取Canvas元素在视口中的真实边界,以此计算触摸点相对于Canvas的坐标。

修改思路

使用Element.getBoundingClientRect()获取Canvas的left和top值(即元素左上角相对于视口的坐标),触摸点的clientX/clientY减去这两个值,就是相对于Canvas内部的正确坐标。

修改后的完整代码

JavaScript

const ctx = c.getContext("2d")

const size = 5,
  Color = "red"

let sx = 0,
  sy = 0

c.ontouchstart = (e) => {
  const rect = c.getBoundingClientRect();
  const t = e.touches[0]
  sx = t.clientX - rect.left
  sy = t.clientY - rect.top
}

c.ontouchmove = (e) => {
  const rect = c.getBoundingClientRect();
  const t = e.touches[0]
  const x = t.clientX - rect.left
  const y = t.clientY - rect.top
  ctx.beginPath()
  ctx.moveTo(sx, sy)
  ctx.lineTo(x, y)
  ctx.lineWidth = size
  ctx.strokeStyle = Color
  ctx.lineCap = "round"
  ctx.stroke()
  sx = x
  sy = y
}

CSS

#d {
  border: none;
  outline: none;
  padding: 0;
}

HTML

<dialog id="d">
  <canvas width="200" height="200" id="c"></canvas>
  <button onclick="d.close()">close</button>
</dialog>
<button onclick="d.showModal()">Open</button>

额外说明

如果后续给Canvas设置了CSS的width/height(和Canvas属性的宽高不一致,即缩放显示),还需要计算缩放比例:

const scaleX = c.width / rect.width;
const scaleY = c.height / rect.height;
// 然后坐标要乘以缩放比例
sx = (t.clientX - rect.left) * scaleX;
sy = (t.clientY - rect.top) * scaleY;

不过你当前的代码没有缩放,所以不需要这一步。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 16:35:01