Я не уверен, какой смысл всех этих ответов, что перебирает родительские элементы и делает все виды странных вещей .
Метод HTMLElement.getBoundingClientRect
предназначен для обработки фактического положения экрана любого элемента. Это включает в себя прокрутку, поэтому такие вещи, как scrollTop
не нужны:
(из MDN) Количество выполненной прокрутки в области области просмотра (или
любой другой прокручиваемый элемент ) учитывается при вычислении
ограничительный прямоугольник
Нормальное изображение
очень простой подход уже был размещен здесь. Это правильно до тех пор, пока не задействованы дикие правила CSS .
Обработка натянутого холста / изображения
Если ширина пикселя изображения не совпадает с шириной CSS, вам нужно применить некоторое отношение к значениям пикселей:
/* Returns pixel coordinates according to the pixel that's under the mouse cursor**/
HTMLCanvasElement.prototype.relativeCoords = function(event) {
var x,y;
//This is the current screen rectangle of canvas
var rect = this.getBoundingClientRect();
var top = rect.top;
var bottom = rect.bottom;
var left = rect.left;
var right = rect.right;
//Recalculate mouse offsets to relative offsets
x = event.clientX - left;
y = event.clientY - top;
//Also recalculate offsets of canvas is stretched
var width = right - left;
//I use this to reduce number of calculations for images that have normal size
if(this.width!=width) {
var height = bottom - top;
//changes coordinates by ratio
x = x*(this.width/width);
y = y*(this.height/height);
}
//Return as an array
return [x,y];
}
Пока холст не имеет границы, он работает для растянутых изображений (jsFiddle) .
Обработка границ CSS
Если холст имеет толстую рамку, все становится немного сложнее . Вам буквально нужно вычесть границу из ограничивающего прямоугольника. Это можно сделать с помощью .getComputedStyle . Этот ответ описывает процесс .
Затем функция немного растет:
/* Returns pixel coordinates according to the pixel that's under the mouse cursor**/
HTMLCanvasElement.prototype.relativeCoords = function(event) {
var x,y;
//This is the current screen rectangle of canvas
var rect = this.getBoundingClientRect();
var top = rect.top;
var bottom = rect.bottom;
var left = rect.left;
var right = rect.right;
//Subtract border size
// Get computed style
var styling=getComputedStyle(this,null);
// Turn the border widths in integers
var topBorder=parseInt(styling.getPropertyValue('border-top-width'),10);
var rightBorder=parseInt(styling.getPropertyValue('border-right-width'),10);
var bottomBorder=parseInt(styling.getPropertyValue('border-bottom-width'),10);
var leftBorder=parseInt(styling.getPropertyValue('border-left-width'),10);
//Subtract border from rectangle
left+=leftBorder;
right-=rightBorder;
top+=topBorder;
bottom-=bottomBorder;
//Proceed as usual
...
}
Я не могу думать ни о чем, что могло бы спутать эту последнюю функцию. Смотрите на JsFiddle .
Примечания
Если вам не нравится изменять собственные prototype
s, просто измените функцию и вызовите ее с помощью (canvas, event)
(и замените любой this
на canvas
).