Canvas网格鼠标高亮异常:红色方块远离原点后尺寸变大
Canvas网格鼠标悬停高亮方块异常放大问题解决
核心问题分析
你的代码里有三个关键错误导致方块随远离原点变大:
ctx.rect()参数误用:Canvas的rect(x, y, width, height)方法后两个参数是方块的宽高,不是结束坐标。你错误地传入了tileEndx和tileEndy(即结束位置),导致越往后的方块宽高越大(比如第n个格子的宽高会是32*(n+1))。- 重复绑定鼠标事件:每次
draw()执行都绑定mousemove事件,会导致事件监听叠加,鼠标移动时多次触发坐标赋值,可能引发异常。 - 鼠标坐标未相对Canvas:使用
clientX/clientY会受Canvas在页面中的位置影响,应该用offsetX/offsetY获取相对Canvas的坐标。
修复后的代码
JavaScript部分
var canvas = document.getElementById("myCanvas"); var ctx = canvas.getContext("2d"); const TILE_SIZE = 32; var xtiles = Math.floor(canvas.width / TILE_SIZE); var ytiles = Math.floor(canvas.height / TILE_SIZE); var posX = 0; var posY = 0; // 只绑定一次鼠标移动事件 canvas.addEventListener('mousemove', (event) => { // 获取相对于Canvas的坐标 posX = event.offsetX; posY = event.offsetY; }); function drawTiles() { // 绘制灰色网格 for (let y = 0; y < ytiles; y++) { for (let x = 0; x < xtiles; x++) { const tileX = x * TILE_SIZE; const tileY = y * TILE_SIZE; ctx.beginPath(); ctx.rect(tileX, tileY, TILE_SIZE, TILE_SIZE); ctx.fillStyle = "grey"; ctx.fill(); ctx.stroke(); ctx.closePath(); } } // 计算高亮方块的位置 const highlightX = Math.floor(posX / TILE_SIZE) * TILE_SIZE; const highlightY = Math.floor(posY / TILE_SIZE) * TILE_SIZE; // 绘制红色高亮方块 ctx.beginPath(); ctx.rect(highlightX, highlightY, TILE_SIZE, TILE_SIZE); ctx.fillStyle = "red"; ctx.fill(); ctx.stroke(); ctx.closePath(); } function draw() { ctx.clearRect(0, 0, canvas.width, canvas.height); drawTiles(); } setInterval(draw, 100);
HTML部分
<canvas id="myCanvas" width="480" height="320"></canvas>
额外优化点
- 用常量
TILE_SIZE统一管理格子大小,方便后续修改 - 简化网格绘制循环,直接通过索引计算格子位置,避免维护start/end变量
- 初始给
posX/posY赋值,避免首次绘制时的undefined问题
内容的提问来源于stack exchange,提问作者user16581612
相关产品推荐
相关产品推荐

