6 сентябр 2025

Koordinatalar

Elementlarni harakatlantirish uchun koordinatalar bilan tanish bo’lishimiz kerak.

JavaScript usullarining ko’pchiligi ikkita koordinata tizimidan biri bilan ishlaydi:

  1. Oynaga nisbatanposition:fixed ga o’xshash, oynaning yuqori/chap chetidan hisoblanadi.
    • bu koordinatalarni clientX/clientY deb belgilaymiz, bunday nomlanishning sababi keyinroq event xususiyatlarini o’rganganimizda aniq bo’ladi.
  2. Hujjatga nisbatan – hujjat ildizidagi position:absolute ga o’xshash, hujjatning yuqori/chap chetidan hisoblanadi.
    • ularni pageX/pageY deb belgilaymiz.

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 = x
  • top = y
  • right = x + width
  • bottom = y + height

E’tibor bering:

  • Koordinatalar 10.5 kabi o’nli kasrlar bo’lishi mumkin. Bu normal, brauzer ichida hisob-kitoblarda kasrlardan foydalanadi. Biz style.left/top ga o’rnatganda ularni yumaloqlashimiz shart emas.
  • Koordinatalar manfiy bo’lishi mumkin. Masalan, agar sahifa shunday skroll qilinganki, elem endi oynadan yuqorida bo’lsa, u holda elem.getBoundingClientRect().top manfiy bo’ladi.
Nega hosila xususiyatlar kerak? Agar 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.

Internet Explorer: x/y qo’llab-quvvatlamaydi

Internet 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.

Koordinatalar right/bottom CSS position xususiyatlaridan farq qiladi

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.

Oynadan tashqari koordinatalar uchun elementFromPoint null qaytaradi

document.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:

  1. Oynaga nisbatan – elem.getBoundingClientRect().
  2. 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.

Vazifalar

muhimlik: 5

Quyidagi iframe-da yashil “maydon” bilan hujjatni ko’rishingiz mumkin.

O’qlar bilan ko’rsatilgan burchaklarning oyna koordinatalarini topish uchun JavaScript-dan foydalaning.

Qulaylik uchun hujjatda kichik xususiyat mavjud. Istalgan joyga bosish u yerdagi koordinatalarni ko’rsatadi.

Sizning kodingiz oyna koordinatalarini olish uchun DOM dan foydalanishi kerak:

  1. Yuqori chap, tashqi burchak (bu oddiy).
  2. Pastki o’ng, tashqi burchak (oddiy ham).
  3. Yuqori chap, ichki burchak (biroz qattiqroq).
  4. Pastki o’ng, ichki burchak (bir necha yo’l bor, birini tanlang).

Siz hisoblagan koordinatalar sichqonchani bosish orqali qaytariladigan koordinatalar bilan bir xil bo’lishi kerak.

P.S. Agar element boshqa o’lcham yoki chegaraga ega bo’lsa, hech qanday sobit qiymatlarga bog’lanmagan bo’lsa, kod ham ishlashi kerak.

Vazifa uchun sandbox-ni oching.

Tashqi burchaklar

Tashqi burchaklar asosan elem.getBoundingClientRect() dan oladigan narsadir.

Yuqori chap burchakdagi answer1 va pastki o’ng burchakdagi answer2 koordinatalari:

let coords = elem.getBoundingClientRect();

let answer1 = [coords.left, coords.top];
let answer2 = [coords.right, coords.bottom];

Chap-yuqori ichki burchak

Bu tashqi burchakdan chegara kengligi bilan farq qiladi. Masofani olishning ishonchli usuli bu clientLeft/clientTop:

let answer3 = [coords.left + field.clientLeft, coords.top + field.clientTop];

O’ng-pastki ichki burchak

Bizning holatda biz tashqi koordinatalardan chegara o’lchamini olib tashlashimiz kerak.

Biz CSS usulidan foydalanishimiz mumkin:

let answer4 = [
  coords.right - parseInt(getComputedStyle(field).borderRightWidth),
  coords.bottom - parseInt(getComputedStyle(field).borderBottomWidth),
];

Chap-yuqori burchakning koordinatalariga clientWidth/clientHeight ni qo‘shish muqobil usul bo‘ladi. Bu, ehtimol, undan ham yaxshiroq:

let answer4 = [
  coords.left + elem.clientLeft + elem.clientWidth,
  coords.top + elem.clientTop + elem.clientHeight,
];

Yechimni sandbox-da oching.

Anchor elementi yaqinidagi pozitsiyaga qarab elem joylashtiradigan positionAt(anchor, position, element) funksiyasini yarating.

Pozitsiya 3 ta qiymatdan biriga ega bo’lgan satr bo’lishi kerak:

  • "top" – pozitsiyada elem anchor tepasiga joylashadi
  • "right" – pozitsiyada elem anchorning o’ng tomonida joylashadi
  • "bottom" – pozitsiyada elem anchor ostida joylashadi

U topshiriqning manba kodida taqdim etilgan showNote(anchor, position, html) funksiyasi ichida qoʻllaniladi, u berilgan html bilan eslatma elementini yaratadi va uni anchor yonidagi berilgan pozitsiyada koʻrsatadi.

Eslatmalar demosi:

Vazifa uchun sandbox-ni oching.

Ushbu vazifada biz faqat koordinatalarni aniq hisoblashimiz kerak. Tafsilotlar uchun kodga qarang.

E’tibor bering: “offsetHeight” va boshqa xususiyatlarni o’qish uchun elementlar hujjatda bo’lishi kerak. Yashirin (displey: yoq) yoki hujjatdan tashqari elementning olchami yo`q.

Yechimni sandbox-da oching.

oldingi vazifa yechimini shunday o’zgartiringki, eslatmada position: fixed o’rniga “position: absolute” ishlatiladi.

Bu sahifa aylantirilganda uning elementdan “qochib ketishini” oldini oladi.

Ushbu vazifaning yechimini boshlang’ich nuqtasi sifatida oling. O’tkazishni sinab ko’rish uchun <body style="height: 2000px"> uslubini qo’shing.

Yechim aslida juda oddiy:

  • .eslatma uchun position: fixed orniga CSS-daposition:absolute` dan foydalaning.
  • Hujjatning nisbiy koordinatalarini olish uchun Koordinatalar bobidagi getCoords() funksiyasidan foydalaning.

Yechimni sandbox-da oching.

Oldingi vazifani Element yaqinidagi eslatmani ko'rsatish (mutlaq) kengaytiring: positionAt(anchor, position, elem) funksiyasiga elem ni anchor ichiga qo’yishni o’rgating.

position uchun yangi qiymatlar:

  • top-out, right-out, bottom-out – avvalgidek ishlaydi, ular elem ni anchor ning ustiga/o’ngiga/ostiga qo’yadi.
  • top-in, right-in, bottom-inelem ni anchor ichiga qo’yadi: uni yuqori/o’ng/pastki chetiga yopishtirib qo’yadi.

Masalan:

// eslatmani blockquote ustida ko'rsatadi
positionAt(blockquote, "top-out", note);

// eslatmani blockquote ichida, yuqorida ko'rsatadi
positionAt(blockquote, "top-in", note);

Natija:

Manba kod sifatida Element yaqinidagi eslatmani ko'rsatish (mutlaq) vazifasining yechimini oling.

O'quv qo'llanma xaritasi

Izohlar

izoh berishdan oldin buni o'qing…
  • Agar sizda nimani yaxshilash kerakligi haqida takliflaringiz bo'lsa - iltimos, GitHub muammosini yuboring yoki izoh berish o'rniga so'rov yuboring.
  • Agar siz maqolada biror narsani tushunolmasangiz - iltimos, batafsilroq ma'lumot bering.
  • Bir nechta so'z so'zlarini kiritish uchun <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…)