【问题标题】:Getting mouse location in canvas [duplicate]在画布中获取鼠标位置[重复]
【发布时间】:2010-11-10 00:16:19
【问题描述】:

有没有办法在<canvas> 标签中获取位置鼠标?我想要相对于<canvas> 右上角的位置,而不是整个页面。

【问题讨论】:

    标签: javascript html canvas


    【解决方案1】:

    从鼠标位置减去画布 DOM 元素的 X 和 Y 偏移,得到画布内的本地位置。

    【讨论】:

    • 如何以适用于所有浏览器的方式获取 canvas dom 元素的 X 和 Y?
    • 很高兴看到有 18k 代表的人提供铺位建议...
    • 介意告诉我为什么我的建议是“废话”吗?您是否认为它不正确,不够详细等?那会更有帮助。此外,我的代表并不一定意味着我的答案会是完美的,这就是为什么会有一个投票系统。不同意?然后投票否决。
    • 您能否解释一下我应该在答案中添加什么以使其更好。我同意它相当笼统,可能需要一个代码示例等。但到目前为止,人们只是说“不好的答案”。
    • 您可以添加如何从 DOM 元素中获取 (x,y) 位置。
    【解决方案2】:

    最简单的方法大概是给canvas元素添加一个onmousemove事件监听器,然后就可以从事件本身获取相对于canvas的坐标了。

    如果您只需要支持特定的浏览器,这很容易实现,但是 f.ex 之间存在差异。歌剧和火狐。

    这样的东西应该适用于这两个:

    function mouseMove(e)
    {
        var mouseX, mouseY;
    
        if(e.offsetX) {
            mouseX = e.offsetX;
            mouseY = e.offsetY;
        }
        else if(e.layerX) {
            mouseX = e.layerX;
            mouseY = e.layerY;
        }
    
        /* do something with mouseX/mouseY */
    }
    

    【讨论】:

    • 我强烈推荐使用 JQuery 或其他一些标准化偏移量的 JavaScript 框架。
    • 这仅适用于我将画布位置设置为 Nat 建议的相对位置。
    • @Richard - 这是因为layerXlayerY 是相对于非定位元素的整个文档。请在此处查看我的答案以获取更多信息:stackoverflow.com/questions/5085689/…
    • 如果定义了 e.offsetX,但等于 0,那么这段代码做错了。
    【解决方案3】:

    另请注意,您需要 CSS:

    位置:相对;

    设置为您的画布标签,以获取画布内的相对鼠标位置。

    如果有边框,偏移量会发生变化

    【讨论】:

    • 一直在互联网上搜索,以找出为什么 Firefox (7) 报告 layerY 的值异常 - 这已解决,非常感谢!
    • 谢谢!那是我的问题。
    • 谢谢,在此之前我得到了不同的值。
    • +1 这解决了我在 FF 11 中遇到的 5-10 像素偏移问题。谢谢!
    • 这不是 onlynecessary 的方法。这个答案应该解释的是e.layerXe.layerY 在它是定位元素时相对于画布,但在不是定位元素时相对于整个文档。请注意,这些属性不是任何标准的一部分。有更好的方法来做到这一点。
    【解决方案4】:

    对于鼠标位置,我通常使用 jQuery,因为它标准化了一些事件属性。

    function getPosition(e) {
    
        //this section is from http://www.quirksmode.org/js/events_properties.html
        var targ;
        if (!e)
            e = window.event;
        if (e.target)
            targ = e.target;
        else if (e.srcElement)
            targ = e.srcElement;
        if (targ.nodeType == 3) // defeat Safari bug
            targ = targ.parentNode;
    
        // jQuery normalizes the pageX and pageY
        // pageX,Y are the mouse positions relative to the document
        // offset() returns the position of the element relative to the document
        var x = e.pageX - $(targ).offset().left;
        var y = e.pageY - $(targ).offset().top;
    
        return {"x": x, "y": y};
    };
    
    // now just make sure you use this with jQuery
    // obviously you can use other events other than click
    $(elm).click(function(event) {
        // jQuery would normalize the event
        position = getPosition(event);
        //now you can use the x and y positions
        alert("X: " + position.x + " Y: " + position.y);
    });
    

    这适用于所有浏览器。

    编辑:

    我从我正在使用的一个类中复制了代码,因此对 this.canvas 的 jQuery 调用是错误的。更新后的函数会找出导致事件的 DOM 元素 (targ),然后使用该元素的偏移量来找出正确的位置。

    【讨论】:

      【解决方案5】:

      GEE 是一个非常有用的库,用于解决画布问题,包括鼠标位置。

      【讨论】:

      • 这个库非常棒,感谢链接。
      • GEE 不再维护,并被开发人员称为“完全弃用”。
      【解决方案6】:

      我将分享迄今为止我创建的最防弹的鼠标代码。它适用于所有浏览器,包括各种填充、边距、边框和附加组件(如 stumbleupon 顶栏)

      // Creates an object with x and y defined,
      // set to the mouse position relative to the state's canvas
      // If you wanna be super-correct this can be tricky,
      // we have to worry about padding and borders
      // takes an event and a reference to the canvas
      function getMouse = function(e, canvas) {
        var element = canvas, offsetX = 0, offsetY = 0, mx, my;
      
        // Compute the total offset. It's possible to cache this if you want
        if (element.offsetParent !== undefined) {
          do {
            offsetX += element.offsetLeft;
            offsetY += element.offsetTop;
          } while ((element = element.offsetParent));
        }
      
        // Add padding and border style widths to offset
        // Also add the <html> offsets in case there's a position:fixed bar (like the stumbleupon bar)
        // This part is not strictly necessary, it depends on your styling
        offsetX += stylePaddingLeft + styleBorderLeft + htmlLeft;
        offsetY += stylePaddingTop + styleBorderTop + htmlTop;
      
        mx = e.pageX - offsetX;
        my = e.pageY - offsetY;
      
        // We return a simple javascript object with x and y defined
        return {x: mx, y: my};
      }
      

      您会注意到我使用了一些在函数中未定义的(可选)变量。它们是:

        stylePaddingLeft = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingLeft'], 10)      || 0;
        stylePaddingTop  = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingTop'], 10)       || 0;
        styleBorderLeft  = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderLeftWidth'], 10)  || 0;
        styleBorderTop   = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderTopWidth'], 10)   || 0;
        // Some pages have fixed-position bars (like the stumbleupon bar) at the top or left of the page
        // They will mess up mouse coordinates and this fixes that
        var html = document.body.parentNode;
        htmlTop = html.offsetTop;
        htmlLeft = html.offsetLeft;
      

      我建议只计算一次,这就是为什么它们不在getMouse 函数中。

      【讨论】:

      • 很棒的小实用方法。我认为在大多数情况下,您也不需要每次都计算画布偏移量。
      【解决方案7】:

      我会使用 jQuery。

      $(document).ready(function() {
      
          $("#canvas_id").bind( "mousedown", function(e){ canvasClick(e); } );
      
      }
      
      function canvasClick( e ){
      
          var x = e.offsetX;
          var y = e.offsetY;
      
      }
      

      这样,您的画布可以位于页面上的任何位置,无论是相对的还是绝对的。

      【讨论】:

        【解决方案8】:

        接受的答案并非每次都有效。如果您不使用相对位置,则属性 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);
        

        【讨论】:

        • 这应该是公认的答案
        【解决方案9】:

        使用鼠标事件和画布属性的简单方法:

        JSFiddle 功能演示 http://jsfiddle.net/Dwqy7/5/
        (注:不考虑边框,导致off-by-one):

        1. 向画布添加鼠标事件
          canvas.addEventListener("mousemove", mouseMoved);

        2. 调整event.clientXevent.clientY基于:
          canvas.offsetLeft
          window.pageXOffset
          window.pageYOffset
          canvas.offsetTop
          因此:

          canvasMouseX = event.clientX - (canvas.offsetLeft - window.pageXOffset); canvasMouseY = event.clientY - (canvas.offsetTop - window.pageYOffset);

        最初的问题要求右上角的坐标(第二个功能)。 这些函数需要在它们可以访问画布元素的范围内。

        0,0 在左上角:

        function mouseMoved(event){
            var canvasMouseX = event.clientX - (canvas.offsetLeft - window.pageXOffset);
            var canvasMouseY = event.clientY - (canvas.offsetTop - window.pageYOffset);
        }
        

        0,0 在右上角:

        function mouseMoved(event){
            var canvasMouseX =  canvas.width - (event.clientX - canvas.offsetLeft)- window.pageXOffset;
            var canvasMouseY = event.clientY - (canvas.offsetTop - window.pageYOffset);
        }
        

        【讨论】:

        • off-by-1-pixel 是你的 1px 边框(边框和内边距也算在内)。您还应该考虑滚动...干杯! :-)
        • @markE 感谢您的提醒;我已经调整了上面和 JSFiddle 中的代码以考虑滚动。我找不到调整画布边框的方法。
        猜你喜欢
        • 2015-02-12
        • 1970-01-01
        • 2011-06-18
        • 1970-01-01
        • 2019-02-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多