Detect mouse click location within canvas

一笑奈何 提交于 2019-12-06 03:23:31

Getting perfect mouse clicks is slightly tricky, I'll share the most bulletproof mouse code that I have created thus far. It works on all browsers will all manner of padding, margin, border, and add-ons (like the stumbleupon top bar).

// 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(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};
}

You'll notice that I use some (optional) variables that are undefined in the function. They are:

  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;

I'd recommend only computing those once, which is why they are not in the getMouse function.


You should really have a single function hat handles mouse clicks, calls getMouse once, and then goes though a list of objects, checking against each one with the x and y. Pseudocode:

function onMouseDown(e) {
  var mouse = getMouse(e, canvas)
  var l = myObjects.length;
  var found = false;

  // Maybe "deselect" them all right here

  for (var i = 0; i < l; i++) {
    if (distance sqrt to myObjects[i]) {
      found = true;
      myObjects[i].ManageClickOrWhateverYouWantHere()
    }
    break;
  }

  // And now we can know if we clicked on empty space or not!
  if (!found) {
    // No objects found at the click, so nothing has been clicked on
    // do some relevant things here because of that
    // I presume from your question this may be part of what you want
  }

}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!