javascript – 获取画布内矩形的光标位置

我有一个画布,里面有一块板/网格.当用户在网格的交叉点上突出显示鼠标时,我希望它显示他们的游戏角色将去哪里.当电路板的尺寸与画布完全相同时,这种方法非常好.我一直把它缩小到x.

因此,如下图所示,绿色显示画布,网格是电路板.我将光标放在绿色的右下角,以显示它何时触发.唯一一个正常工作的是中间的,因为无论我制作多大的板,中间总是中间的.

任何简单的修复只是使用鼠标悬停事件来创建区域,而不是画布而是事件监听器在画布上.我的代码在图片下方

《javascript – 获取画布内矩形的光标位置》

变量:

var canvas = document.getElementById("game-canvas");
var context = canvas.getContext("2d");

var boardSize = 13;
var border = canvas.width / 20;
var boardWidth = canvas.width - (border * 2);
var boardHeight = canvas.height - (border * 2);

var cellWidth = boardWidth / (boardSize - 1);
var cellHeight = boardHeight / (boardSize - 1);

var lastX;
var lastY;

鼠标悬停事件:

canvas.addEventListener('mousemove', function(evt) 
{
    var position = getGridPoint(evt);

    if ((position.x != lastX) || (position.y != lastY))
    {
        placeStone((position.x * cellWidth) + border, (position.y * cellWidth) + border, 'rgba(0, 0, 0, 0.2)');         
    }

    lastX = position.x;
    lastY = position.y;     
});

获取网格上的点并将其转换为数字0 – 13(在本例中)

function getGridPoint(evt)
{
    var rect = canvas.getBoundingClientRect();

    var x = Math.round((evt.clientX-rect.left)/(rect.right-rect.left)*boardWidth);
    var y = Math.round((evt.clientY-rect.top)/(rect.bottom-rect.top)*boardHeight);

    var roundX = Math.round(x / cellWidth);
    var roundY = Math.round(y / cellHeight);

    return {
      x: roundX,
      y: roundY
    };
}

最后在板上画出一块:

function placeStone(x, y, color)
{
    var radius = cellWidth / 2;

    context.beginPath();
    context.arc(x, y, radius, 0, 2 * Math.PI, false);
    context.fillStyle = color;  
    context.fill();
    context.lineWidth = 5;
}

我留下了几个像网格刷新的一样,所以它不是跟随你的鼠标和东西的一串圆圈,以保持它尽可能短,我希望它只是一个简单的asnwer没有人需要重新创建它,但如果你这样做我可以包括刷新网格和绘制所有内容的功能.谢谢你的任何建议

最佳答案 获得相对于盒子的位置

// just as an example w,h are width and height
const box = { x : 10, y : 10, w : 100, h : 100 };
// mouse is the mouse coords and relative to the topleft of canvas (0,0);
var mouse.box = {}
mouse.box.x = mouse.x - box.x;
mouse.box.y = mouse.y - box.y;

mouse.box x,y的负值和大于框宽度和高度的值都在鼠标外部.

为了更方便,您可以在框中对鼠标进行标准化

mouse.box.nx = mouse.box.x / box.w;
mouse.box.ny = mouse.box.y / box.h;

当在盒子的内部或边缘时,nx,ny的坐标在0-1的范围内;

如果您想要网格位置,则定义网格

box.gridW = 10; // grid divisions width
box.gridH = 10; // grid divisions height

然后得到鼠标的网格pos

mouse.box.gx = Math.floor(mouse.box.nx * box.gridW);
mouse.box.gy = Math.floor(mouse.box.ny * box.gridH);
const ctx = canvas.getContext("2d");


const box = { x : 50,y : 10, w : 200, h : 200, gridW : 10, gridH : 10}


function drawGrid(){
    var sx = box.w / box.gridW;
    var sy = box.h / box.gridH;
    var bx = box.x;
    var by = box.y;
    for(var y = 0; y < box.gridH; y ++){
        for(var x = 0; x < box.gridW; x ++){
            ctx.strokeRect(x * sx + bx, y * sx + by,sx,sy);
        }
    }
    if(mouse.box){
      if(mouse.box.nx >= 0  && mouse.box.nx <= 1 &&
      mouse.box.ny >= 0  && mouse.box.ny <= 1){
          ctx.fillRect(mouse.box.gx * sx + bx, mouse.box.gy * sx + by,sx,sy);
      
         }
    }
         
}
const mouse = {};
canvas.addEventListener("mousemove",(e)=>{
    mouse.x = e.pageX;
    mouse.y = e.pageY;
});

function updateMouse(){
    if(!mouse.box){
        mouse.box = {};
    }
    mouse.box.x = mouse.x - box.x;
    mouse.box.y = mouse.y - box.y;
    mouse.box.nx = mouse.box.x / box.w;
    mouse.box.ny = mouse.box.y / box.h;
    mouse.box.gx = Math.floor(mouse.box.nx * box.gridW);
    mouse.box.gy = Math.floor(mouse.box.ny * box.gridH);
    var p = 20;
    ctx.fillText("x : " + mouse.x,box.x+box.w+10,p); p+= 14;
    ctx.fillText("y : " + mouse.y,box.x+box.w+10,p); p+= 20;
    ctx.fillText("Box relative",box.x+box.w+10,p); p+= 14;
    ctx.fillText("x : " + mouse.box.x,box.x+box.w+10,p); p+= 14;
    ctx.fillText("y : " + mouse.box.y,box.x+box.w+10,p); p+= 14;
    ctx.fillText("nx : " + mouse.box.nx,box.x+box.w+10,p); p+= 14;
    ctx.fillText("ny : " + mouse.box.ny,box.x+box.w+10,p); p+= 14;
    ctx.fillText("gx : " + mouse.box.gx,box.x+box.w+10,p); p+= 14;
    ctx.fillText("gy : " + mouse.box.gy,box.x+box.w+10,p); p+= 14;
}

function mainLoop(time){
    if(canvas.width !== innerWidth || canvas.height !== innerHeight){ // resize canvas if window size has changed
        canvas.width = innerWidth;
        canvas.height = innerHeight;
    }
    ctx.setTransform(1,0,0,1,0,0); // set default transform
    ctx.clearRect(0,0,canvas.width,canvas.height); // clear the canvas
    updateMouse();
    drawGrid();
    requestAnimationFrame(mainLoop);
}
requestAnimationFrame(mainLoop);
canvas {
    position : absolute;
    top : 0px;
    left : 0px;
}
<canvas id=canvas><canvas>
点赞