关于如何在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};
};
由于这段代码属于我的库,并且可以接受用户给它的任何画布元素,所以当用户给库一个带边框的画布时,事情就会破裂。有没有考虑到边界的解决方案?
以下是我在最近的实验中使用的内容。
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栏)。如果浏览器被缩放,它也可以工作。
它似乎在触摸设备上也很好用。
试试这个:
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};
};
clientLeft
和clientTop
包括边界,而offsetLeft
和offsetTop
不包括边界。
如果你不想包含其他元素,也许以下内容会起作用:
this.getPosition = function(obj) {
return{'x': obj.clientLeft,
'y': obj.clientTop};
};