СиÑÑема кооÑÐ´Ð¸Ð½Ð°Ñ Ð¾ÑноÑиÑелÑно ÑÑÑаниÑÑ Ð¸Ð»Ð¸, инаÑе говоÑÑ, оÑноÑиÑелÑно докÑменÑа, наÑинаеÑÑÑ Ð² левом-веÑÑ Ð½ÐµÐ¼ ÑглÑ, но не окна, а именно ÑÑÑаниÑÑ.
РкооÑдинаÑÑ Ð² ней ознаÑаÑÑ Ð¿Ð¾Ð·Ð¸ÑÐ¸Ñ Ð¿Ð¾ оÑноÑÐµÐ½Ð¸Ñ Ð½Ðµ к Ð¾ÐºÐ½Ñ Ð±ÑаÑзеÑа, а к докÑменÑÑ Ð² Ñелом.
ÐÑли пÑовеÑÑи Ð°Ð½Ð°Ð»Ð¾Ð³Ð¸Ñ Ñ CSS, Ñо кооÑдинаÑÑ Ð¾ÑноÑиÑелÑно окна â ÑÑо position:fixed, а оÑноÑиÑелÑно докÑменÑа â position:absolute (пÑи позиÑиониÑовании вне дÑÑгиÑ
ÑлеменÑов, еÑÑеÑÑвенно).
ÐÑ Ð±Ñдем назÑваÑÑ ÐºÐ¾Ð¾ÑдинаÑÑ Ð² ней pageX/pageY.
Ðни нÑÐ¶Ð½Ñ Ð² пеÑвÑÑ Ð¾ÑеÑÐµÐ´Ñ Ð´Ð»Ñ Ñого, ÑÑÐ¾Ð±Ñ Ð¿Ð¾ÐºÐ°Ð·ÑваÑÑ ÑÐ»ÐµÐ¼ÐµÐ½Ñ Ð² опÑеделÑнном меÑÑе ÑÑÑаниÑÑ, а не окна.
СÑавнение ÑиÑÑем кооÑдинаÑ
Ðогда ÑÑÑаниÑа не пÑокÑÑÑена, ÑоÑки наÑала кооÑÐ´Ð¸Ð½Ð°Ñ Ð¾ÑноÑиÑелÑно окна (clientX,clientY) и докÑменÑа (pageX,pageY) ÑовпадаÑÑ:
ÐапÑимеÑ, кооÑдинаÑÑ ÑлеменÑа Ñ Ð½Ð°Ð´Ð¿Ð¸ÑÑÑ Â«STANDARDS» ÑÐ°Ð²Ð½Ñ ÑаÑÑÑоÑÐ½Ð¸Ñ Ð¾Ñ Ð²ÐµÑÑ Ð½ÐµÐ¹/левой гÑаниÑÑ Ð¾ÐºÐ½Ð°:
ÐÑокÑÑÑим ÑÑÑаниÑÑ, ÑÑÐ¾Ð±Ñ ÑÐ»ÐµÐ¼ÐµÐ½Ñ Ð±Ñл на Ñамом веÑÑ Ñ:
ÐоÑмоÑÑиÑе на ÑиÑÑнок ниже, на нÑм â Ñа же ÑÑÑаниÑа, ÑолÑко пÑокÑÑÑеннаÑ, и ÑÐ¾Ñ Ð¶Ðµ ÑÐ»ÐµÐ¼ÐµÐ½Ñ Â«STANDARDS».
- ÐооÑдинаÑа
clientYизменилаÑÑ. Ðна бÑла175, а ÑÑала0, Ñак как ÑÐ»ÐµÐ¼ÐµÐ½Ñ Ð½Ð°Ñ Ð¾Ð´Ð¸ÑÑÑ Ð²Ð²ÐµÑÑ Ñ Ð¾ÐºÐ½Ð°. - ÐооÑдинаÑа
pageYоÑÑалаÑÑ Ñакой же, Ñак как оÑÑÑиÑÑваеÑÑÑ Ð¾Ñ Ð»ÐµÐ²Ð¾Ð³Ð¾-веÑÑ Ð½ÐµÐ³Ð¾ Ñгла докÑменÑа.
ÐÑак, кооÑдинаÑÑ pageX/pageY не менÑÑÑÑÑ Ð¿Ñи пÑокÑÑÑке, в оÑлиÑие Ð¾Ñ clientX/clientY.
ÐолÑÑение кооÑдинаÑ
Ð ÑожалениÑ, гоÑовой ÑÑнкÑии Ð´Ð»Ñ Ð¿Ð¾Ð»ÑÑÐµÐ½Ð¸Ñ ÐºÐ¾Ð¾ÑÐ´Ð¸Ð½Ð°Ñ ÑлеменÑа оÑноÑиÑелÑно ÑÑÑаниÑÑ Ð½ÐµÑ. Ðо ÐµÑ Ð¼Ð¾Ð¶Ð½Ð¾ легко напиÑаÑÑ Ñамим.
ÐÑи две ÑиÑÑÐµÐ¼Ñ ÐºÐ¾Ð¾ÑÐ´Ð¸Ð½Ð°Ñ Ð¶ÑÑÑко ÑвÑзанÑ: pageY = clientY + ÑекÑÑÐ°Ñ Ð²ÐµÑÑикалÑÐ½Ð°Ñ Ð¿ÑокÑÑÑка.
ÐаÑа ÑÑнкÑÐ¸Ñ getCoords(elem) бÑÐ´ÐµÑ Ð±ÑаÑÑ ÑезÑлÑÑÐ°Ñ elem.getBoundingClientRect() и пÑибавлÑÑÑ ÑекÑÑÑÑ Ð¿ÑокÑÑÑÐºÑ Ð´Ð¾ÐºÑменÑа.
РезÑлÑÑÐ°Ñ getCoords: обÑÐµÐºÑ Ñ ÐºÐ¾Ð¾ÑдинаÑами {left: .., top: ..}
function getCoords(elem) { // кÑоме IE8-
var box = elem.getBoundingClientRect();
return {
top: box.top + pageYOffset,
left: box.left + pageXOffset
};
}
ÐÑли нÑжно поддеÑживаÑÑ Ð±Ð¾Ð»ÐµÐµ ÑÑаÑÑе IE, Ñо Ð²Ð¾Ñ Ð°Ð»ÑÑеÑнаÑивнÑй, ÑамÑй кÑоÑÑ-бÑаÑзеÑнÑй ваÑианÑ:
function getCoords(elem) {
// (1)
var box = elem.getBoundingClientRect();
var body = document.body;
var docEl = document.documentElement;
// (2)
var scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop;
var scrollLeft = window.pageXOffset || docEl.scrollLeft || body.scrollLeft;
// (3)
var clientTop = docEl.clientTop || body.clientTop || 0;
var clientLeft = docEl.clientLeft || body.clientLeft || 0;
// (4)
var top = box.top + scrollTop - clientTop;
var left = box.left + scrollLeft - clientLeft;
return {
top: top,
left: left
};
}
РазбеÑÑм ÑÑо и заÑем, по Ñагам:
- ÐолÑÑаем пÑÑмоÑголÑник.
- СÑиÑаем пÑокÑÑÑÐºÑ ÑÑÑаниÑÑ. ÐÑе бÑаÑзеÑÑ, кÑоме IE8- поддеÑживаÑÑ ÑвойÑÑво
pageXOffset/pageYOffset. Рболее ÑÑаÑÑÑ IE, когда ÑÑÑановлен DOCTYPE, пÑокÑÑÑÐºÑ Ð¼Ð¾Ð¶Ð½Ð¾ полÑÑиÑÑ Ð¸Ð·documentElement, Ð½Ñ Ð¸ Ð½Ð°ÐºÐ¾Ð½ÐµÑ ÐµÑли DOCTYPE некоÑÑекÑен â иÑполÑзоваÑÑbody. - Ð IE докÑÐ¼ÐµÐ½Ñ Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ ÑмеÑÑн оÑноÑиÑелÑно левого веÑÑ Ð½ÐµÐ³Ð¾ Ñгла. ÐолÑÑим ÑÑо ÑмеÑение.
- Ðобавим пÑокÑÑÑÐºÑ Ðº кооÑдинаÑам окна и вÑÑÑем ÑмеÑение
html/body, ÑÑÐ¾Ð±Ñ Ð¿Ð¾Ð»ÑÑиÑÑ ÐºÐ¾Ð¾ÑдинаÑÑ Ð½Ñжного нам ÑлеменÑа.
УÑÑаÑевÑий меÑод: offset*
ÐÑÑÑ Ð°Ð»ÑÑеÑнаÑивнÑй ÑпоÑоб наÑ
Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ ÐºÐ¾Ð¾ÑÐ´Ð¸Ð½Ð°Ñ â ÑÑо пÑойÑи вÑÑ ÑепоÑÐºÑ offsetParent Ð¾Ñ ÑлеменÑа ввеÑÑ
и ÑложиÑÑ Ð¾ÑÑÑÑÐ¿Ñ offsetLeft/offsetTop.
ÐÑ ÑазбиÑаем его здеÑÑ Ñ ÑÑебной ÑелÑÑ, Ñак как он иÑполÑзÑеÑÑÑ Ð»Ð¸ÑÑ Ð² ÑÑаÑÑÑ Ð±ÑаÑзеÑÐ°Ñ .
ÐÐ¾Ñ ÑÑнкÑиÑ, ÑеализÑÑÑÐ°Ñ Ñакой Ð¿Ð¾Ð´Ñ Ð¾Ð´.
function getOffsetSum(elem) {
var top = 0,
left = 0;
while (elem) {
top = top + parseInt(elem.offsetTop);
left = left + parseInt(elem.offsetLeft);
elem = elem.offsetParent;
}
return {
top: top,
left: left
};
}
ÐазалоÑÑ Ð±Ñ, код ноÑмалÑнÑй. Рон как-Ñо ÑабоÑаеÑ, но ÑазнÑе бÑаÑзеÑÑ Ð¿ÑеподноÑÑÑ Â«ÑÑÑпÑизÑ», вклÑÑÐ°Ñ Ð¸Ð»Ð¸ вÑклÑÑÐ°Ñ ÑÐ°Ð·Ð¼ÐµÑ Ñамок и пÑокÑÑÑок из offsetTop/Left, некоÑÑекÑно ÑÑиÑÑÐ²Ð°Ñ Ð¿Ð¾Ð·Ð¸ÑиониÑование. РиÑоге ÑезÑлÑÑÐ°Ñ Ð½Ðµ вÑегда веÑен. Ðожно, конеÑно, ÑазобÑаÑÑ ÑÑи пÑÐ¾Ð±Ð»ÐµÐ¼Ñ Ð¸ поÑÑиÑаÑÑ Ð´ÐµÐ¹ÑÑвиÑелÑно аккÑÑаÑно и пÑавилÑно ÑÑим ÑпоÑобом, но заÑем? ÐÐµÐ´Ñ ÐµÑÑÑ getBoundingClientRect.
ÐÑ Ð¼Ð¾Ð¶ÐµÑе ÑвидеÑÑ ÑазниÑÑ Ð¼ÐµÐ¶Ð´Ñ Ð²ÑÑиÑлением кооÑÐ´Ð¸Ð½Ð°Ñ ÑеÑез offset* и getBoundingClientRect на пÑимеÑе.
РпÑÑмоÑголÑнике ниже еÑÑÑ 3 вложеннÑÑ
DIV. ÐÑе они имеÑÑ border, кое-кÑо из ниÑ
Ð¸Ð¼ÐµÐµÑ position/margin/padding.
ÐликниÑе по внÑÑÑÐµÐ½Ð½ÐµÐ¼Ñ (жÑлÑомÑ) ÑлеменÑÑ, ÑÑÐ¾Ð±Ñ ÑвидеÑÑ ÑезÑлÑÑаÑÑ Ð¾Ð±Ð¾Ð¸Ñ
меÑодов: getOffsetSum и getCoords, а Ñакже ÑеалÑнÑе кооÑдинаÑÑ ÐºÑÑÑоÑа â event.pageX/pageY (Ð¼Ñ Ð¾Ð±ÑÑдим иÑ
позже в ÑÑаÑÑе ÐÑÑÑ: IE8-, иÑпÑавление ÑобÑÑиÑ).
ÐÑи клике на лÑбом меÑÑе жÑлÑого блока Ð²Ñ Ð»ÐµÐ³ÐºÐ¾ ÑвидиÑе ÑазниÑÑ Ð¼ÐµÐ¶Ð´Ñ getOffsetSum(elem) и getCoords(elem).
ÐÐ»Ñ Ñого, ÑÑÐ¾Ð±Ñ ÑзнаÑÑ, какой же ÑезÑлÑÑÐ°Ñ Ð²ÐµÑнÑй, кликниÑе в левом-веÑÑ
нем ÑÐ³Ð»Ñ Ð¶ÑлÑого блока, пÑиÑÑм обÑаÑиÑе внимание â кликаÑÑ Ð½Ñжно не на жÑлÑом, а на ÑÑÑном, ÑÑо Ñамка, она Ñоже вÑ
Ð¾Ð´Ð¸Ñ Ð² ÑлеменÑ. ÐÑдÑÑ Ð²Ð¸Ð´Ð½Ñ ÑоÑнÑе кооÑдинаÑÑ Ð¼ÑÑи, Ñак ÑÑо Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе ÑÑавниÑÑ Ð¸Ñ
Ñ getOffsetSum/getCoords.
ÐÑÐ¸Ð¼ÐµÑ ÐºÐ»Ð¸ÐºÐ° в пÑавилÑном меÑÑе (обÑаÑиÑе внимание на ÑазниÑÑ ÐºÐ¾Ð¾ÑдинаÑ):
Ðменно getCoords вÑегда возвÑаÑÐ°ÐµÑ Ð²ÐµÑное знаÑение.
ÐооÑдинаÑÑ Ð½Ð° ÑкÑане screenX/screenY
ÐÑÑÑ ÐµÑÑ Ð¾Ð´Ð½Ð° ÑиÑÑема кооÑдинаÑ, коÑоÑÐ°Ñ Ð¸ÑполÑзÑеÑÑÑ Ð¾ÑÐµÐ½Ñ Ñедко, но Ð´Ð»Ñ Ð¿Ð¾Ð»Ð½Ð¾ÑÑ ÐºÐ°ÑÑÐ¸Ð½Ñ Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾ ÐµÑ ÑпомÑнÑÑÑ.
ÐооÑдинаÑÑ Ð¾ÑноÑиÑелÑно ÑкÑана screenX/screenY оÑÑÑиÑÑваÑÑÑÑ Ð¾Ñ ÐµÐ³Ð¾ левого-веÑÑ
него Ñгла. ÐмееÑÑÑ Ð² Ð²Ð¸Ð´Ñ Ð¸Ð¼ÐµÐ½Ð½Ð¾ веÑÑ ÑкÑан, а не окно бÑаÑзеÑа.
Такие кооÑдинаÑÑ Ð¼Ð¾Ð³ÑÑ Ð±ÑÑÑ Ð¿Ð¾Ð»ÐµÐ·Ð½Ñ, напÑимеÑ, пÑи ÑабоÑе Ñ Ð¼Ð¾Ð±Ð¸Ð»ÑнÑми ÑÑÑÑойÑÑвами или Ð´Ð»Ñ Ð¾ÑкÑÑÑÐ¸Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ окна поÑеÑедине ÑкÑана вÑзовом window.open.
-
РазмеÑÑ ÑкÑана Ñ ÑанÑÑÑÑ Ð² глобалÑной пеÑеменной screen:
// обÑÐ°Ñ ÑиÑина/вÑÑоÑа alert( screen.width + ' x ' + screen.height ); // доÑÑÑÐ¿Ð½Ð°Ñ ÑиÑина/вÑÑоÑа (за вÑÑеÑом ÑаÑкбаÑа и Ñ.п.) alert( screen.availWidth + ' x ' + screen.availHeight ); // еÑÑÑ Ð¸ ÑÑд дÑÑÐ³Ð¸Ñ ÑвойÑÑв screen (Ñм. докÑменÑаÑиÑ) -
ÐооÑдинаÑÑ Ð»ÐµÐ²Ð¾Ð³Ð¾-веÑÑ Ð½ÐµÐ³Ð¾ Ñгла бÑаÑзеÑа на ÑкÑане Ñ ÑанÑÑÑÑ Ð²
window.screenX,window.screenY(не поддеÑживаÑÑÑÑ IE8-):alert( "ÐÑаÑÐ·ÐµÑ Ð½Ð°Ñ Ð¾Ð´Ð¸ÑÑÑ Ð½Ð° " + window.screenX + "," + window.screenY );Ðни могÑÑ Ð±ÑÑÑ Ð¸ менÑÑе нÑлÑ, еÑли окно ÑаÑÑиÑно вне ÑкÑана.
ÐамеÑим, ÑÑо обÑÑÑ Ð¸Ð½ÑоÑмаÑÐ¸Ñ Ð¾Ð± ÑкÑане и бÑаÑзеÑе полÑÑиÑÑ Ð¼Ð¾Ð¶Ð½Ð¾, а Ð²Ð¾Ñ ÐºÐ¾Ð¾ÑдинаÑÑ ÐºÐ¾Ð½ÐºÑеÑного ÑлеменÑа на ÑкÑане â нелÑзÑ, Ð½ÐµÑ Ð°Ð½Ð°Ð»Ð¾Ð³Ð° getBoundingClientRect или иного меÑода Ð´Ð»Ñ ÑÑого.
ÐÑого
У лÑбой ÑоÑки в бÑаÑзеÑе еÑÑÑ ÐºÐ¾Ð¾ÑдинаÑÑ:
- ÐÑноÑиÑелÑно окна
windowâelem.getBoundingClientRect(). - ÐÑноÑиÑелÑно докÑменÑа
documentâ добавлÑем пÑокÑÑÑкÑ, во вÑÐµÑ ÑÑеймвоÑÐºÐ°Ñ ÐµÑÑÑ Ð³Ð¾ÑÐ¾Ð²Ð°Ñ ÑÑнкÑиÑ. - ÐÑноÑиÑелÑно ÑкÑана
screenâ можно ÑзнаÑÑ ÐºÐ¾Ð¾ÑдинаÑÑ Ð±ÑаÑзеÑа, но не ÑлеменÑа.
Ðногда в ÑÑаÑом коде можно вÑÑÑеÑиÑÑ Ð¸ÑполÑзование offsetTop/Left Ð´Ð»Ñ Ð¿Ð¾Ð´ÑÑÑÑа кооÑдинаÑ. ÐÑо оÑÐµÐ½Ñ ÑÑаÑÑй и непÑавилÑнÑй ÑпоÑоб, не ÑÑÐ¾Ð¸Ñ ÐµÐ³Ð¾ иÑполÑзоваÑÑ.
ÐооÑдинаÑÑ Ð±ÑдÑÑ Ð½ÑÐ¶Ð½Ñ Ð½Ð°Ð¼ далее, пÑи ÑабоÑе Ñ ÑобÑÑиÑми мÑÑи (кооÑдинаÑÑ ÐºÐ»Ð¸ÐºÐ°) и ÑлеменÑами (пеÑемеÑение).
ÐомменÑаÑии
<code>, Ð´Ð»Ñ Ð½ÐµÑколÑÐºÐ¸Ñ ÑÑÑок кода — Ñег<pre>, еÑли болÑÑе 10 ÑÑÑок — ÑÑÑÐ»ÐºÑ Ð½Ð° пеÑоÑниÑÑ (plnkr, JSBin, codepenâ¦)