HTML5画布滚动会干扰鼠标位置

6

我现在正在研究HTML5,并想编写一些小型浏览器游戏——只是为了好玩。我创建了一个画布,在其中加载了一个背景图像——它有点像六边形网格。为了找出单击了哪个六边形,我使用了圆形及其中心/半径。我解释这些,因为这样您可以更快地理解我发布的代码。

这一切都很顺利,直到我使用滚动条时——然后一切都乱了。似乎是我获取的坐标不正确。由于网格有点大,所以我必须在小屏幕上特别使用滚动条。

以下是代码:

网站链接

<html>
<head>
    <script type="text/javascript" src="worldmap.js"></script>
    <script type="text/javascript" src="worldmapMouseEvents.js"></script>
</head>
<body onload="draw()">

    Xcoord: <div id="xcoord">0</div>&nbsp;
Ycoord: <div id="ycoord">0</div><br>
Spalte: <div id="column">0</div><br>
Reihe: <div id="row">0</div><br>  

   <canvas id="canvas" 
    width="1100" 
    height="1100"
    style="border: 1px solid black;" 
    onmousemove="getMousePosition()"
    onmousedown="getCell()">
   </canvas>

</body>
</html> 

显示网格的文件为worldmap.js。
function draw(){
  var c=document.getElementById("canvas");
  var ctx=c.getContext("2d");
  var img = new Image();

  img.onload = function(){ 
      ctx.drawImage(img,0,0);
      ctx.stroke();
  };
  img.src = './pics/grid.jpg';
}

这里是更多的源文件worldmapMouseEvents.js,它在滚动后表现得很奇怪。

function getMousePosition() {
 var x = new Number();
 var y = new Number();
 var canvas = document.getElementById("canvas");

 if (event.x != undefined && event.y != undefined) {
    x = event.x;
    y = event.y;
 } else 
 {
    x = event.clientX + document.body.scrollLeft
            + document.documentElement.scrollLeft;
    y = event.clientY + document.body.scrollTop
            + document.documentElement.scrollTop;
 }

 x -= canvas.offsetLeft;
 y -= canvas.offsetTop;

return [x,y];
}

这里是一个计算哪个六边形被点击的函数,它使用圆来进行计算(数学运算正确且相当简单:(xCoord - xCenter)^2 + (yCoord -yCenter)^2。如果半径^2小于或等于该点,则该点位于圆内。开始的这些数组只是网格中心坐标。)

function getCell(){

var xOddRows = new Array(25, 65, 105, 145, 185, 225, 265, 305, 345, 385, 425, 465, 505, 545, 585, 625, 665, 705, 745, 785, 825, 865, 905, 945, 985);
var yOddRows = new Array(35, 115, 195, 275, 355, 435, 515, 595, 675, 755, 835, 915, 995);

var xEvenRows = new Array(45, 84, 125, 165, 205, 245, 285, 325, 365, 405, 445, 485, 525, 565, 605, 645, 685, 725, 765, 805, 845, 885, 925, 965, 1005);
var yEvenRows = new Array(75, 155, 235, 315, 395, 475, 555, 635, 715, 795, 875, 955);

var position = getMousePosition();
var x = position[0];
var y = position[1];


for(var yOddRowsRunner = 0; yOddRowsRunner < 13; yOddRowsRunner++){
    for( var xOddRowsRunner = 0; xOddRowsRunner < 25; xOddRowsRunner++){
        var circle = (x - xOddRows[xOddRowsRunner])*(x - xOddRows[xOddRowsRunner]) + (y - yOddRows[yOddRowsRunner])*(y - yOddRows[yOddRowsRunner]);
        var radius = (20 * 20);

        if(radius >= circle){
            yPos = (2 * yOddRowsRunner) +1 ;//This is just for nicer output
            return [yPos, xOddRowsRunner];
        }
    }
}

for(var yEvenRowsRunner = 0; yEvenRowsRunner < 12; yEvenRowsRunner++){
    for( var xEvenRowsRunner = 0; xEvenRowsRunner < 25; xEvenRowsRunner++){
        var circle = (x - xEvenRows[xEvenRowsRunner])*(x - xEvenRows[xEvenRowsRunner]) + (y -  yEvenRows[yEvenRowsRunner])*(y -  yEvenRows[yEvenRowsRunner]);
        var radius = (20 * 20);

        if(radius >= circle){
                        yPos = (2 * yEvenRowsRunner) +2; //This is just for nicer output
                return [yPos, xEvenRowsRunner];
        }
    }
}

return null;    
}

这是完整的代码,就像我说的那样,只要不使用滚动条,它就可以正常工作。非常感谢您的帮助 - 这整个过程让我感到疯狂。


1
好的 - 我看到了我的错误。我只是不知道那个。我刚刚写了一个大的“谢谢”作为评论。 - Daniel
1个回答

11

我之前也遇到过类似的问题;最终我通过使用类似于你尝试过的方法解决了它;我将 .x 和 .y 替换为 .pageX 和 .pageY。

if (e.pageX || e.pageY) { 
    x = e.pageX;
    y = e.pageY;
}
据我所知,这是因为 .x 和 .y 不是相对于元素抓取坐标,而是相对于整个页面抓取坐标;换句话说,它们没有考虑滚动,而 pageX 和 pageY 则考虑了。 使用 .x 和 .y 的测试用例 使用 pageX 和 pageY 的测试用例

1
使用e.PageX和e.PageY是更好的解决方案。如果你的画布在一个可滚动的元素内,当窗口不在滚动位置0,0时,pageX和pageY将报告不正确的值,因此我建议添加这一点。 - Matt Jensen
我有客户X和客户Y,遇到了类似的问题。谢谢您,应该将其标记为答案。 - owen gerig

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接