【问题标题】:Get cursor location of a rectangle inside a canvas获取画布内矩形的光标位置
【发布时间】:2017-05-31 20:31:21
【问题描述】:

我有一个画布,里面有一个板/网格。当用户在网格的交叉点上突出显示他们的鼠标时,我希望它显示他们的游戏将去哪里。当电路板与画布的确切尺寸相同时,这非常有效。我一直把它变小x。

如下图所示,绿色表示画布,网格表示板。我将光标放在绿色的右下角以显示它何时触发。唯一可以正常工作的是中间那个,因为不管我把板子做多大,中间永远是中间。

任何简单的解决方法就是使用鼠标悬停事件创建区域,板的尺寸而不是画布,但事件侦听器位于画布上。我的代码在图片下方

变量:

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,没有人需要重新创建它但是如果你这样做,我可以包含刷新网格并绘制所有内容的功能。谢谢你的任何建议

【问题讨论】:

    标签: javascript html canvas


    【解决方案1】:

    获取相对于框的位置

    // 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
    

    然后获取鼠标的网格位置

    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;
    }
    &lt;canvas id=canvas&gt;&lt;canvas&gt;

    【讨论】:

    • 我想我明白你的意思,只是将原点(0,0)移到盒子的原点。 - 更改了这个var x = Math.round((evt.clientX-rect.left) - border/(rect.right-rect.left)*boardWidth);,所以它包括 - 边框,它似乎工作正常,我觉得我错过了一些东西但我找不到它,谢谢 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-28
    • 2012-09-28
    相关资源
    最近更新 更多