使用JavaScript在画布内获取鼠标位置

11
我正在学习jQuery和HTML5画布。我想要做一个简单的HTML5绘图例子,当鼠标移动时,在我的鼠标下方绘制红色正方形。 我的代码很简单,但是我在获取画布内鼠标光标位置时遇到了问题。现在,我使用x = event.offsetX; 来获取鼠标位置。这在Chrome中非常有效,但是在Firefox中不起作用。我将代码更改为x = event.layerX。但似乎layerX是相对于网页而不是画布的鼠标位置,因此我总是看到一个偏移量。 我有两个问题:第一,如何在Firefox下获取正确的鼠标位置?第二,如何编写可以在IE、Firefox、Chrome、Safari和Opera上运行的代码? 这是我的代码:
 <!doctype html />
<html><head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
  $(document).ready(
 function(){

var flip = document.getElementById('flip');
    var context = flip.getContext('2d');   
context.fillStyle = "rgb(255,255,255)";   
context.fillRect(0, 0, 500, 500);

      $("a").click(function(event){alert("Thanks for visiting!");});
   $("#flip").mousemove(function(event){
      var x, y;


    x = event.layerX;
    y = event.layerY;


    //alert("mouse pos"+event.layerX );
    var flip = document.getElementById('flip');
    var context = flip.getContext('2d');   
context.fillStyle = "rgb(255,0,0)";   
context.fillRect(x, y, 5, 5);
    }
   );
  }
  );    
  </script>
  </head>  <body bgcolor="#000000"> <a href="http://jquery.com/">jQuery</a><canvas id="flip" width="500" height="500">
  This text is displayed if your browser does not support HTML5 Canvas.</canvas> </body></html>

4
<!doctype html /> 是无效的,会触发怪异模式(quirks mode),这会改变很多 DOM 行为!正确的 DTD 是 <!doctype html> - Delan Azabani
3个回答

16

我看到很多关于这个主题的问题,所有的解决方案都建议浏览DOM或使用offsetX和offsetY,但它们并不总是被正确设置。

你应该使用canvas API中的函数:canvas.getBoundingClientRect()。

  function getMousePos(canvas, evt) {
    var rect = canvas.getBoundingClientRect();
    return {
      x: evt.clientX - rect.left,
      y: evt.clientY - rect.top
    };
  }

  canvas.addEventListener('mousemove', function(evt) {
    var mousePos = getMousePos(canvas, evt);
    console.log('Mouse position: ' + mousePos.x + ',' + mousePos.y);
  }, false);

1
这是一个不错的解决方案,但如果画布带有边框或填充样式,它将无法正常工作... - Bernat Romagosa
1
getBoundingClientRect() 返回边框盒子的矩形,但这是我发现唯一以相同方式处理位置样式和滚动的解决方案。 使用此解决方案,您将不得不使用一些丑陋的代码,例如: parseInt(canvas.style.borderLeftWidth.substring(-2) 我的建议是:在父 div 上添加 padding 和 border。 - AxFab

11

在这里输入图片描述

<!DOCTYPE html>

<html>
    <head>
        <meta charset = "utf-8">

        <script>
            Element.prototype.leftTopScreen = function () {
                var x = this.offsetLeft;
                var y = this.offsetTop;

                var element = this.offsetParent;

                while (element !== null) {
                    x = parseInt (x) + parseInt (element.offsetLeft);
                    y = parseInt (y) + parseInt (element.offsetTop);

                    element = element.offsetParent;
                }

                return new Array (x, y);
            }

            document.addEventListener ("DOMContentLoaded", function () {
                var flip = document.getElementById ("flip");

                var xy = flip.leftTopScreen ();

                var context = flip.getContext ("2d");

                context.fillStyle = "rgb(255,255,255)";   
                context.fillRect (0, 0, 500, 500);

                flip.addEventListener ("mousemove", function (event) {
                    var x = event.clientX;
                    var y = event.clientY;

                    context.fillStyle = "rgb(255, 0, 0)";  
                    context.fillRect (x - xy[0], y - xy[1], 5, 5);
                });
            });    
        </script>

        <style>
            #flip {
                border: 1px solid black;
                display: inline-block;

            }

            body {
                text-align: center;
            }
        </style>
    </head>

    <body>
        <canvas id = "flip" width = "500" height = "500">This text is displayed if your browser does not support HTML5 Canvas.</canvas>
    </body>
</html>

你不必担心兼容性,只有IE(9之前的版本)不原生支持canvas。


1
这个答案解决了问题,但不明智地扩展了DOM并重新发明了轮子。 - Wayne
4
<!doctype html /> 是无效的,会触发怪异模式(quirks mode),导致很多DOM操作的行为变化!正确的DTD声明是 <!doctype html> - Delan Azabani
如果窗口没有向上滚动,您的leftTopOffset函数会出现错误。 - Thom Wiggers

2

您需要一个自定义函数来确定元素的位置,然后确定鼠标在该元素内的位置。 这里是一个例子。它使用了quirks模式下的这个函数和我的JavaScript库,应该不难将其翻译成jQuery。

function findPos(obj) {
    var curleft = curtop = 0;

    if (obj.offsetParent) {
        do {
            curleft += obj.offsetLeft;
            curtop += obj.offsetTop;
        } while (obj = obj.offsetParent);

        return [curleft, curtop];
    }
}

编辑

这段代码在IE上无法运行,因为IE不支持pageX属性。你需要通过像这个函数将事件对象传递来进行修正。但是正如2x2p1p所说,canvas在低于9版本的任何Internet Explorer中都不受支持。


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