UI hodisalari

Skroll

scroll hodisasi foydalanuvchi sahifani yoki elementni skroll qilganda ishga tushadi. Bundan foydali narsalar qilish mumkin: skroll pozitsiyasiga qarab qo'shimcha kontent yuklash, "yuqoriga" tugmasini ko'rsatish, yoki skroll bo'yicha animatsiyalar qilish. Bu darsda skrollning o'ziga xosliklarini chuqur ko'rib chiqamiz.

Bu darsdagi misollar statik โ€” skroll hodisasi playground'da ishlamaydi. Ularni haqiqiy sahifada sinang.

scroll hodisasi

scroll hodisasi windowda (butun sahifa skrolli uchun) yoki istalgan skrollanadigan elementda ishlaydi:

window.addEventListener('scroll', function() {
  console.log('Skroll pozitsiyasi: ' + window.pageYOffset);
});

Joriy skroll miqdorini bir necha usul bilan bilish mumkin:

window.addEventListener('scroll', function() {
  // Sahifa oxiriga qanchalik yaqinligini hisoblaymiz
  let scrolledToBottom =
    window.pageYOffset + window.innerHeight >=
    document.documentElement.scrollHeight - 100;
  if (scrolledToBottom) {
    console.log('Sahifa oxiriga yaqinlashdik');
  }
});
scroll hodisasi juda tez-tez ishga tushadi (foydalanuvchi skroll qilganda har lahzada). Shuning uchun ishlov beruvchi ichida og'ir hisob-kitob qilmang. Zarur bo'lsa, throttle (chastotani cheklash) yoki requestAnimationFrame texnikasini qo'llang โ€” aks holda sahifa "sekinlashadi" (lag).

Skrollni scroll hodisasi bilan to'xtatib bo'lmaydi

Muhim va ko'pincha adashtiradigan nuqta: scroll hodisasida event.preventDefault() chaqirsangiz ham, skroll to'xtamaydi.

Sabab: scroll hodisasi skroll allaqachon sodir bo'lgandan keyin ishga tushadi โ€” ya'ni u "xabar berish" (reaksiya) hodisasi, boshqarish hodisasi emas. Uni bekor qilib skrollni orqaga qaytarib bo'lmaydi.

// BU ISHLAMAYDI โ€” skroll baribir sodir bo'ladi:
window.addEventListener('scroll', function(event) {
  event.preventDefault(); // hech qanday ta'sir yo'q
});

Skrollni to'g'ri oldini olish usullari

Skrollning oldini olish uchun uni keltirib chiqaruvchi hodisani to'xtatish kerak. Masalan, klaviatura yoki sichqoncha g'ildiragi (wheel) hodisasini:

Eng ishonchli va oddiy yechim esa CSS orqali: elementga overflow: hidden berish skrollni butunlay o'chiradi. Modal oynalar ochilganda tagdagi sahifa skrollini bloklashda aynan shu ishlatiladi:

// Modal ochilganda tagdagi sahifa skrollini bloklash:
document.body.style.overflow = 'hidden';

// Modal yopilganda tiklash:
document.body.style.overflow = '';
Yana bir zamonaviy CSS xossasi โ€” overscroll-behavior. U skroll bir elementdan otasiga "o'tib ketishini" (scroll chaining) nazorat qiladi. Masalan, ichki panel oxiriga yetganda butun sahifaning skroll bo'lib ketishini oldini olishda foydali.

Amaliy misol: "Yuqoriga" tugmasi

Skrollga qarab tugmani ko'rsatish/yashirishning oddiy misoli. Foydalanuvchi ma'lum masofaga pastga tushganda "yuqoriga qaytish" tugmasi paydo bo'ladi:

window.addEventListener('scroll', function() {
  if (window.pageYOffset > 500) {
    upButton.style.display = 'block';
  } else {
    upButton.style.display = 'none';
  }
});

upButton.onclick = function() {
  window.scrollTo({ top: 0, behavior: 'smooth' });
};

Cheksiz sahifa (infinite scroll)

"Cheksiz sahifa" โ€” bu ko'p ijtimoiy tarmoqlarda ko'radigan xatti-harakat: foydalanuvchi pastga skroll qilgani sari yangi kontent avtomatik yuklanadi va sahifa "tugamaydi". Bunga scroll hodisasi asosida erishiladi.

G'oya sodda: har bir skrollda hujjat oxiriga qancha yaqin qolganini tekshiramiz. Agar yetarlicha yaqin bo'lsak โ€” yangi kontent bo'lagini yuklab, sahifa oxiriga qo'shamiz:

window.addEventListener('scroll', function() {
  // Hujjatning ko'rinmas (past) qismi 100px dan kam qolsa
  let windowRelativeBottom =
    document.documentElement.getBoundingClientRect().bottom;

  if (windowRelativeBottom < document.documentElement.clientHeight + 100) {
    // Yangi kontent yuklaymiz va qo'shamiz
    loadMoreContent();
  }
});

Bu yerda mantiq:

Cheksiz skrollda ehtiyot bo'lish kerak: loadMoreContent bir necha marta ketma-ket chaqirilmasligi uchun "yuklanmoqda" bayrog'ini (flag) qo'ying, aks holda bir skrollda o'nlab so'rov jo'natilib ketishi mumkin:
let isLoading = false;

window.addEventListener('scroll', function() {
  if (isLoading) return; // allaqachon yuklanmoqda
  // ...oxiriga yaqin ekanligini tekshiramiz...
  if (nearBottom) {
    isLoading = true;
    loadMoreContent().then(function() {
      isLoading = false;
    });
  }
});
Zamonaviy loyihalarda cheksiz skroll uchun scroll hodisasi o'rniga ko'pincha IntersectionObserver ishlatiladi โ€” u sahifa oxiriga qo'yilgan "nishon" element ko'rinishga kirganini samaraliroq va tejamli kuzatadi. scroll hodisasidan farqli, u har lahzada ishga tushmaydi.

Xulosa