Elementlarni harakatlantirish uchun koordinatalar bilan tanish bo’lishimiz kerak.
JavaScript usullarining ko’pchiligi ikkita koordinata tizimidan biri bilan ishlaydi:
- Oynaga nisbatan –
position:fixedga o’xshash, oynaning yuqori/chap chetidan hisoblanadi.- bu koordinatalarni
clientX/clientYdeb belgilaymiz, bunday nomlanishning sababi keyinroq event xususiyatlarini o’rganganimizda aniq bo’ladi.
- bu koordinatalarni
- Hujjatga nisbatan – hujjat ildizidagi
position:absolutega o’xshash, hujjatning yuqori/chap chetidan hisoblanadi.- ularni
pageX/pageYdeb belgilaymiz.
- ularni
Sahifa eng boshigacha skroll qilinganda, ya’ni oynaning yuqori/chap burchagi aynan hujjatning yuqori/chap burchagi bo’lganda, bu koordinatalar bir-biriga teng bo’ladi. Ammo hujjat siljigandan keyin, elementlarning oynaga nisbatan koordinatalari o’zgaradi, chunki elementlar oyna bo’ylab harakatlanadilar, hujjatga nisbatan koordinatalar esa bir xil qoladi.
Ushbu rasmda biz hujjatdagi nuqtani olamiz va skrolldan oldingi (chap) va keyingi (o’ng) koordinatalarini ko’rsatamiz:
Hujjat skroll qilinganda:
pageY– hujjatga nisbatan koordinata bir xil qoldi, u hujjat yuqorisidan hisoblanadi (hozir skroll qilingan).clientY– oynaga nisbatan koordinata o’zgaradi (o’q qisqaroq bo’ldi), chunki xuddi shu nuqta oyna yuqorisiga yaqinroq bo’ldi.
Element koordinatalari: getBoundingClientRect
elem.getBoundingClientRect() usuli elem ni o’rab turgan minimal to’rtburchak uchun oyna koordinatalarini o’rnatilgan DOMRect sinfi obyekti sifatida qaytaradi.
Asosiy DOMRect xususiyatlari:
x/y– to’rtburchak boshlanishining oynaga nisbatan X/Y koordinatalari,width/height– to’rtburchakning kengligi/balandligi (manfiy bo’lishi mumkin).
Qo’shimcha ravishda, hosila xususiyatlar mavjud:
top/bottom– yuqori/pastki to’rtburchak cheti uchun Y-koordinata,left/right– chap/o’ng to’rtburchak cheti uchun X-koordinata.
Misol uchun, ushbu tugmani bosing va uning oyna koordinatalarini ko’ring:
Agar sahifani skroll qilsangiz va takrorlasangiz, oynaga nisbatan tugma holati o’zgarganligi sababli, uning oyna koordinatalari (vertikal skroll qilsangiz y/top/bottom) ham o’zgarishini sezasiz.
Mana elem.getBoundingClientRect() natijasining tasviri:
Ko’rib turganingizdek, x/y va width/height to’rtburchakni to’liq tasvirlaydi. Hosila xususiyatlar ulardan osongina hisoblanishi mumkin:
left = xtop = yright = x + widthbottom = y + height
E’tibor bering:
- Koordinatalar
10.5kabi o’nli kasrlar bo’lishi mumkin. Bu normal, brauzer ichida hisob-kitoblarda kasrlardan foydalanadi. Bizstyle.left/topga o’rnatganda ularni yumaloqlashimiz shart emas. - Koordinatalar manfiy bo’lishi mumkin. Masalan, agar sahifa shunday skroll qilinganki,
elemendi oynadan yuqorida bo’lsa, u holdaelem.getBoundingClientRect().topmanfiy bo’ladi.
x/y mavjud bo’lsa, nima uchun top/left mavjud?Matematik jihatdan to’rtburchak o’zining boshlang’ich nuqtasi (x,y) va yo’nalish vektori (width,height) bilan noyob tarzda aniqlanadi. Shunday qilib, qo’shimcha hosila xususiyatlar qulaylik uchun.
Texnik jihatdan width/height ning manfiy bo’lishi mumkin, bu “yo’naltirilgan” to’rtburchak uchun imkon beradi, masalan sichqon tanlovini to’g’ri belgilangan boshlanish va oxiri bilan ifodalash uchun.
Mana manfiy width va height bo’lgan to’rtburchak (masalan width=-200, height=-100):
Ko’rib turganingizdek, bunday holatda left/top x/y ga teng emas.
Amalda esa elem.getBoundingClientRect() har doim musbat kenglik/balandlik qaytaradi, bu yerda manfiy width/height ni faqat bu bir xil ko’rinadigan xususiyatlar aslida takrorlanmasligi sababini tushunishingiz uchun eslatamiz.
x/y qo’llab-quvvatlamaydiInternet Explorer tarixiy sabablarga ko’ra x/y xususiyatlarini qo’llab-quvvatlamaydi.
Shunday qilib, biz yoki polyfill yasashimiz mumkin (DomRect.prototype da getterlar qo’shish) yoki shunchaki top/left dan foydalanishimiz mumkin, chunki ular musbat width/height uchun, xususan elem.getBoundingClientRect() natijasida har doim x/y bilan bir xil.
Oynaga nisbatan koordinatalar va CSS position:fixed o’rtasida aniq o’xshashliklar bor.
Ammo CSS joylashtirishda right xususiyati o’ng chetdan masofani, bottom xususiyati esa pastki chetdan masofani anglatadi.
Yuqoridagi rasmga nazar tashlaydigan bo’lsak, JavaScript da bunday emasligini ko’ramiz. Barcha oyna koordinatalari chap-yuqori burchakdan hisoblanadi, ularni ham o’z ichiga olgan holda.
elementFromPoint(x, y)
document.elementFromPoint(x, y) ga chaqiruv oyna koordinatalari (x, y) dagi eng ichki joylashgan elementni qaytaradi.
Sintaksis:
let elem = document.elementFromPoint(x, y);
Masalan, quyidagi kod oynaning o’rtasida hozir turgan elementni ajratib ko’rsatadi va uning tegini chiqaradi:
let centerX = document.documentElement.clientWidth / 2;
let centerY = document.documentElement.clientHeight / 2;
let elem = document.elementFromPoint(centerX, centerY);
elem.style.background = "red";
alert(elem.tagName);
Oyna koordinatalaridan foydalanganligi sababli, element joriy skroll holatiga qarab farq qilishi mumkin.
elementFromPoint null qaytaradidocument.elementFromPoint(x,y) usuli faqat (x,y) ko’rinadigan maydon ichida bo’lsa ishlaydi.
Agar koordinatalardan birortasi manfiy bo’lsa yoki oyna kengligi/balandligidan oshsa, u null qaytaradi.
Mana uni tekshirmasak yuz berishi mumkin bo’lgan tipik xato:
let elem = document.elementFromPoint(x, y);
// agar koordinatalar oynadan tashqarida bo'lsa, elem = null
elem.style.background = ''; // Xato!
“Fixed” joylashtirishda foydalanish
Ko’pincha bizga biror narsani joylashtirishda koordinatalar kerak bo’ladi.
Element yonida biror narsani ko’rsatish uchun biz uning koordinatalarini olish uchun getBoundingClientRect dan foydalanishimiz va keyin CSS position ni left/top (yoki right/bottom) bilan birga ishlatishimiz mumkin.
Masalan, quyidagi createMessageUnder(elem, html) funksiyasi elem ostida xabar ko’rsatadi:
let elem = document.getElementById("coords-show-mark");
function createMessageUnder(elem, html) {
// xabar elementi yaratish
let message = document.createElement('div');
// bu yerda uslub uchun css sinfidan foydalanish yaxshiroq
message.style.cssText = "position:fixed; color: red";
// koordinatalar belgilash, "px" ni unutmang!
let coords = elem.getBoundingClientRect();
message.style.left = coords.left + "px";
message.style.top = coords.bottom + "px";
message.innerHTML = html;
return message;
}
// Foydalanish:
// hujjatga 5 soniyaga qo'shish
let message = createMessageUnder(elem, 'Salom, dunyo!');
document.body.append(message);
setTimeout(() => message.remove(), 5000);
Ishga tushirish uchun tugmani bosing:
Kodni chapga, o’ngga, pastga ko’rsatish, CSS animatsiyalarini qo’llash va boshqalar uchun o’zgartirish mumkin. Bu oson, chunki bizda elementning barcha koordinatalari va o’lchamlari bor.
Ammo muhim detailga e’tibor bering: sahifa skroll qilinganda xabar tugmadan uzoqlashadi.
Sababi aniq: xabar elementi position:fixed ga tayanadi, shuning uchun sahifa skroll qilinganda oynaning bir xil joyida qoladi.
Buni o’zgartirish uchun bizga hujjat asosidagi koordinatalar va position:absolute dan foydalanish kerak.
Hujjat koordinatalari
Hujjatga nisbatan koordinatalar oyna emas, balki hujjatning chap-yuqori burchagidan boshlanadi.
CSS da oyna koordinatalari position:fixed ga mos keladi, hujjat koordinatalari esa yuqorida joylashgan position:absolute ga o’xshaydi.
Biz biror narsani hujjatning ma’lum joyiga qo’yish uchun position:absolute va top/left dan foydalanishimiz mumkin, shunda sahifa skroll qilinayotganda ham u o’sha yerda qoladi. Ammo avval to’g’ri koordinatalar kerak.
Elementning hujjat koordinatalarini olish uchun standart usul yo’q. Ammo uni yozish oson.
Ikki koordinata tizimi quyidagi formula bilan bog’langan:
pageY=clientY+ hujjatning skroll qilingan vertikal qismining balandligi.pageX=clientX+ hujjatning skroll qilingan gorizontal qismining kengligi.
getCoords(elem) funksiyasi elem.getBoundingClientRect() dan oyna koordinatalarini olib, ularga joriy skrollni qo’shadi:
// elementning hujjat koordinatalarini olish
function getCoords(elem) {
let box = elem.getBoundingClientRect();
return {
top: box.top + window.pageYOffset,
right: box.right + window.pageXOffset,
bottom: box.bottom + window.pageYOffset,
left: box.left + window.pageXOffset
};
}
Agar yuqoridagi misolda biz uni position:absolute bilan ishlatsak, xabar skroll qilinganda element yonida qoladi.
O’zgartirilgan createMessageUnder funksiyasi:
function createMessageUnder(elem, html) {
let message = document.createElement('div');
message.style.cssText = "position:absolute; color: red";
let coords = getCoords(elem);
message.style.left = coords.left + "px";
message.style.top = coords.bottom + "px";
message.innerHTML = html;
return message;
}
Xulosa
Sahifadagi har qanday nuqta koordinatalarga ega:
- Oynaga nisbatan –
elem.getBoundingClientRect(). - Hujjatga nisbatan –
elem.getBoundingClientRect()plus joriy sahifa skrolli.
Oyna koordinatalari position:fixed bilan ishlatish uchun ajoyib, hujjat koordinatalari esa position:absolute bilan yaxshi ishlaydi.
Ikki koordinata tizimi ham o’z afzalliklari va kamchiliklariga ega; bizga ba’zida biri yoki boshqasi kerak bo’ladi, xuddi CSS position absolute va fixed kabi.
Izohlar
<code>yorlig'ini ishlating, bir nechta satrlar uchun - ularni<pre>yorlig'i bilan o'rab qo'ying, 10 satrdan ortiq bo'lsa - sandbox (plnkr, jsbin, codepen…)