解决HTML Canvas尺寸放大后绘制位置与鼠标偏移的问题
Canvas绘制位置与鼠标点击偏差的解决方法
问题根源在于Canvas存在两个独立的尺寸:
- 绘图缓冲区尺寸:由canvas元素的
width和height属性控制,这是Canvas实际用来绘制图形的像素尺寸,默认是300x150。 - 显示尺寸:由CSS的
width和height控制,只是把缓冲区的像素拉伸/压缩到页面上的显示大小。
你只通过CSS设置了全屏显示,但绘图缓冲区还是默认尺寸,导致鼠标坐标和绘图坐标的比例不匹配,出现偏差。
解决步骤:
- 同步绘图缓冲区与显示尺寸:初始化时将canvas的
width和height属性设置为窗口的实际像素大小,确保缓冲区和显示区域像素一一对应。 - 处理窗口 resize 事件:当窗口大小改变时,重新更新缓冲区尺寸,避免拉伸变形。
- 修正鼠标坐标转换:将鼠标的客户端坐标转换为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
相关产品推荐
相关产品推荐

