【问题标题】:Find coordinates of an HTML5 Canvas (click) event, with borders查找带有边框的 HTML5 Canvas(单击)事件的坐标
【发布时间】:2012-09-09 19:56:47
【问题描述】:

在 Stack Overflow 上有很多关于如何获取 Canvas 元素上的事件相对于 Canvas 本身的坐标的答案。我正在使用以下解决方案 (getEventPosition),它运行良好,除了,当我向我的画布添加边框时:

/**** This solution gives me an offset equal to the border size
 **** when the canvas has a border. Example:
 **** <canvas style='border: 10px solid black; background: #333;' id='gauge_canvas' width='500' height='500'></canvas>
 ****/

// Get DOM element position on page
this.getPosition = function(obj) {
    var x = 0, y = 0;
    if (obj.offsetParent) {
        do {
            x += obj.offsetLeft;
            y += obj.offsetTop;
            obj = obj.offsetParent;
        } while (obj);
    }
    return {'x': x, 'y': y};
};

// Get mouse event position in DOM element (don't know how to use scale yet).
this.getEventPosition = function(e, obj, aux_e, scale) {

    var evt, docX, docY, pos;

    evt = (e ? e : window.event);
    if (evt.pageX || evt.pageY) {
        docX = evt.pageX;
        docY = evt.pageY;
    } else if (evt.clientX || evt.clientY) {
        docX = evt.clientX + document.body.scrollLeft +
            document.documentElement.scrollLeft;
        docY = evt.clientY + document.body.scrollTop +
            document.documentElement.scrollTop;
    }
    // This works on hammer.js
    else if (typeof aux_e !== 'undefined') {
        docX = aux_e.touches[0].x;
        docY = aux_e.touches[0].y;
    }
    pos = this.getPosition(obj);
    if (typeof scale === 'undefined') {
        scale = 1;
    }
    return {'x': (docX - pos.x) / scale, 'y': (docY - pos.y) / scale};
};

由于此代码属于我的库,并且可以获取用户提供的任何画布元素,因此当用户为库提供带边框的画布时,事情就会破裂。是否有考虑边界的解决方案?

【问题讨论】:

    标签: javascript html css canvas dom-events


    【解决方案1】:

    这是我在最近的实验中一直使用的。

    http://jsfiddle.net/simonsarris/te8GQ/5/

    var stylePaddingLeft = parseInt(document.defaultView.getComputedStyle(can, undefined)['paddingLeft'], 10) || 0;
    var stylePaddingTop = parseInt(document.defaultView.getComputedStyle(can, undefined)['paddingTop'], 10) || 0;
    var styleBorderLeft = parseInt(document.defaultView.getComputedStyle(can, undefined)['borderLeftWidth'], 10) || 0;
    var styleBorderTop = parseInt(document.defaultView.getComputedStyle(can, undefined)['borderTopWidth'], 10) || 0;
    var html = document.body.parentNode;
    var htmlTop = html.offsetTop;
    var htmlLeft = html.offsetLeft;
    
    function getMouse(e) {
        var element = can,
            offsetX = 0,
            offsetY = 0,
            mx, my;
    
        // Compute the total offset
        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
        offsetX += stylePaddingLeft + styleBorderLeft + htmlLeft;
        offsetY += stylePaddingTop + styleBorderTop + htmlTop;
    
        mx = e.pageX - offsetX;
        my = e.pageY - offsetY;
    
        // We return a simple javascript object (a hash) with x and y defined
        return {
            x: mx,
            y: my
        };
    }
    

    它适用于任何边框和填充,也适用于在偏移 HTML 的对象中填充的页面(如 stumbleupon 栏)。如果浏览器被缩放,它也可以工作。

    它似乎在触摸设备上也能正常工作。

    【讨论】:

      【解决方案2】:

      试试这个:

      this.getPosition = function(obj) {
          var x = 0, y = 0;
          if (obj.offsetParent) {
              do {
                  x += obj.clientLeft;
                  y += obj.clientTop;
                  obj = obj.offsetParent;
              } while (obj);
          }
          return {'x': x, 'y': y};
      };
      

      clientLeftclientTop 包含边框,但 offsetLeftoffsetTop 不包含。

      如果您不想包含其他元素,也许以下方法会起作用:

      this.getPosition = function(obj) {
          return{'x': obj.clientLeft,
                 'y': obj.clientTop};
      };
      

      【讨论】:

      • 这不仅不能解决问题,还会将画布顶部的两个 h1 元素的高度添加到它返回的 y 坐标中:(
      • @janesconference 我已经编辑了我的答案,试试吧。也许你可以提供一个包含所有代码的 jsfiddle 来测试它。
      猜你喜欢
      • 2023-01-07
      • 2013-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-19
      • 2014-06-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多