IntersectionObserver's coming into view

IntersectionObservers به شما اطلاع می‌دهد که عنصر مشاهده‌شده چه زمانی وارد نمای مرورگر می‌شود یا از آن خارج می‌شود.

Browser Support

  • Chrome: 51.
  • Edge: 15.
  • Firefox: 55.
  • Safari: 12.1.

Source

فرض کنید می‌خواهید زمانی را که عنصری در DOM شما وارد ناحیه نمایش نمایان می‌شود ردیابی کنید. ممکن است بخواهید این کار را انجام دهید تا بتوانید تصاویر را به‌موقع بارگیری کُند کنید یا به این دلیل که باید بدانید آیا کاربر واقعاً به یک برنمای آگهی خاص نگاه می‌کند یا نه. می‌توانید این کار را با متصل کردن رویداد پیمایش یا بااستفاده از زمان‌سنج دوره‌ای و فراخوانی getBoundingClientRect() در آن عنصر انجام دهید.

اما این رویکرد به‌طور آزاردهنده‌ای کند است زیرا هر فراخوانی getBoundingClientRect() مرورگر را مجبور می‌کند کل صفحه را دوباره چیدمان کند و باعث ایجاد لرزش قابل‌توجهی در وب‌سایت شما می‌شود. وقتی می‌دانید سایتتان در iframe بار می‌شود و می‌خواهید بدانید کاربر چه زمانی می‌تواند عنصری را ببیند، کار تقریباً غیرممکن می‌شود. «مدل منبع واحد» و مرورگر به شما اجازه نمی‌دهند به هیچ داده‌ای از صفحه وب حاوی iframe دسترسی داشته باشید. این مشکل رایجی برای آگهی‌ها است، برای مثال، آگهی‌هایی که مکرراً بااستفاده از iframe بار می‌شوند.

IntersectionObserver برای این طراحی شده است که این آزمایش رؤیت‌پذیری را کارآمدتر کند و در همه مرورگرهای نو ارائه شده است. IntersectionObserver به شما اطلاع می‌دهد که عنصر مشاهده‌شده چه زمانی وارد نمای مرورگر می‌شود یا از آن خارج می‌شود.

رؤیت‌پذیری Iframe

نحوه ایجاد IntersectionObserver

این API نسبتاً کوچک است و بااستفاده از یک مثال بهتر توصیف می‌شود:

const io = new IntersectionObserver(entries => {
  console.log(entries);
}, {
  /* Using default options. Details below */
});

// Start observing an element
io.observe(element);

// Stop observing an element
// io.unobserve(element);

// Disable entire IntersectionObserver
// io.disconnect();

بااستفاده از گزینه‌های پیش‌فرض برای IntersectionObserver، هم وقتی عنصر تاحدودی در نما قرار می‌گیرد و هم وقتی کاملاً از نمای دید خارج می‌شود، فراخوانی برگشتی شما فراخوانده می‌شود.

اگر لازم است چندین عنصر را مشاهده کنید، هم ممکن است و هم توصیه می‌شود که چندین عنصر را بااستفاده از همان نمونه IntersectionObserver با چندین بار فراخوانی observe() مشاهده کنید.

پارامتر entries به فراخوانی برگشتی شما ارسال می‌شود که آرایه‌ای از اشیای IntersectionObserverEntry است. هریک از این اشیاء حاوی داده‌های تقاطع به‌روزشده برای یکی از عناصر مشاهده‌شده شما است.

🔽[IntersectionObserverEntry]
    time: 3893.92
    🔽rootBounds: ClientRect
        bottom: 920
        height: 1024
        left: 0
        right: 1024
        top: 0
        width: 920
    🔽boundingClientRect: ClientRect
    // ...
    🔽intersectionRect: ClientRect
    // ...
    intersectionRatio: 0.54
    🔽target: div#observee
    // ...

rootBounds نتیجه فراخوانی getBoundingClientRect() در عنصر ریشه است که به‌طور پیش‌فرض ناحیه نمایش است. boundingClientRect نتیجه getBoundingClientRect() است که در عنصر مشاهده‌شده فراخوانی شده است. intersectionRect تقاطع این دو مستطیل است و به‌طور مؤثر به شما می‌گوید کدام بخش از عنصر مشاهده‌شده قابل‌مشاهده است. intersectionRatio ارتباط نزدیکی دارد و به شما می‌گوید چه مقدار از عنصر نمایان است. با این اطلاعاتی که دراختیار دارید، اکنون می‌توانید ویژگی‌هایی مانند بار کردن به‌موقع دارایی‌ها را قبل‌از اینکه در صفحه نمایان شوند پیاده‌سازی کنید. کارآمد.

نسبت تقاطع.

‫IntersectionObserverها داده‌هایشان را به‌صورت ناهمگام ارائه می‌دهند و کد فراخوانی شما در رشته اصلی اجرا خواهد شد. علاوه‌براین، مشخصات درواقع می‌گوید که پیاده‌سازی‌های IntersectionObserver باید از requestIdleCallback() استفاده کنند. این یعنی فراخوانی به فراخوان برگشتی ارائه‌شده شما اولویت پایینی دارد و مرورگر آن را در زمان بیکاری انجام خواهد داد. این یک تصمیم آگاهانه در طراحی است.

پیمایش divs

من طرفدار پروپاقرص پیمایش درون یک عنصر نیستم، اما اینجا نیستم که قضاوت کنم، و IntersectionObserver هم همین‌طور. شیء options گزینه root را می‌گیرد که به شما امکان می‌دهد جایگزینی برای نمای هدف به‌عنوان ریشه تعریف کنید. باید به‌خاطر داشته باشید که root باید جد همه عناصر مشاهده‌شده باشد.

همه چیز را قطع کنید!

نه! توسعه‌دهنده بد! این کار استفاده آگاهانه از چرخه‌های واحد پردازش مرکزی کاربر نیست. بیایید به‌عنوان مثال به یک پیمایشگر بی‌نهایت فکر کنیم: در آن سناریو، قطعاً توصیه می‌شود که نگهبان‌ها را به DOM اضافه کنید و آن‌ها را مشاهده (و بازیافت!) کنید. باید یک نگهبان نزدیک به آخرین مورد در پیمایشگر بی‌نهایت اضافه کنید. وقتی آن نگهبان در دید قرار می‌گیرد، می‌توانید از فراخوانی برگشتی برای بار کردن داده‌ها، ایجاد موارد بعدی، پیوست کردن آن‌ها به DOM، و تغییر موقعیت نگهبان براساس آن استفاده کنید. اگر نگهبان را به‌درستی بازیافت کنید، نیازی به تماس اضافی با observe() نیست. IntersectionObserver همچنان کار می‌کند.

پیمایشگر بی‌نهایت

به‌روزرسانی‌های بیشتر، لطفاً

همان‌طور که قبلاً ذکر شد، وقتی عنصر مشاهده‌شده تاحدی در نما قرار می‌گیرد، فراخوانی برگشتی یک‌بار راه‌اندازی می‌شود و وقتی از نمای هدف خارج می‌شود، بار دیگر راه‌اندازی می‌شود. به این ترتیب IntersectionObserver به این سؤال پاسخ می‌دهد: «آیا عنصر X در نما است؟». بااین‌حال، در برخی موارد استفاده، ممکن است این کافی نباشد.

اینجا است که گزینه threshold وارد بازی می‌شود. این ویژگی به شما امکان می‌دهد آرایه‌ای از آستانه‌های intersectionRatio را تعریف کنید. هربار که intersectionRatio از یکی از این مقادیر عبور کند، فراخوانی برگشتی شما فراخوانده می‌شود. مقدار پیش‌فرض برای threshold، [0] است که رفتار پیش‌فرض را توضیح می‌دهد. اگر threshold را به [0, 0.25, 0.5, 0.75, 1] تغییر دهیم، هربار که یک‌چهارم دیگر از عنصر نمایان شود، اعلان دریافت خواهیم کرد:

پویانمایی آستانه.

گزینه دیگری هست؟

درحال‌حاضر، فقط یک گزینه دیگر علاوه‌بر گزینه‌های فهرست‌شده در بالا وجود دارد. rootMargin به شما امکان می‌دهد حاشیه‌های ریشه را مشخص کنید، که به‌طور مؤثری به شما اجازه می‌دهد ناحیه مورداستفاده برای تقاطع‌ها را افزایش یا کاهش دهید. این حاشیه‌ها بااستفاده از رشته‌ای به‌سبک CSS، مانند "10px 20px 30px 40px"، مشخص می‌شوند که به‌ترتیب حاشیه بالا، راست، پایین، و چپ را مشخص می‌کند. به‌طور خلاصه، ساختار گزینه‌های IntersectionObserver گزینه‌های زیر را ارائه می‌دهد:

new IntersectionObserver(entries => {/* … */}, {
  // The root to use for intersection.
  // If not provided, use the top-level document's viewport.
  root: null,
  // Same as margin, can be 1, 2, 3 or 4 components, possibly negative lengths.
  // If an explicit root element is specified, components may be percentages of the
  // root element size.  If no explicit root element is specified, using a
  // percentage is an error.
  rootMargin: "0px",
  // Threshold(s) at which to trigger callback, specified as a ratio, or list of
  // ratios, of (visible area / total area) of the observed element (hence all
  // entries must be in the range [0, 1]).  Callback will be invoked when the
  // visible ratio of the observed element crosses a threshold in the list.
  threshold: [0],
});

‫<iframe> جادویی

IntersectionObserver به‌طور خاص با درنظر گرفتن سرویس‌های آگهی و ابزارک‌های شبکه‌های اجتماعی طراحی شده‌اند که اغلب از عناصر <iframe> استفاده می‌کنند و می‌توانند از دانستن اینکه آیا در دید هستند یا نه بهره‌مند شوند. اگر یک <iframe> یکی از عناصر خود را مشاهده کند، هم پیمایش <iframe> و هم پیمایش پنجره حاوی <iframe>، فراخوانی برگشتی را در زمان‌های مناسب فعال می‌کند. اما برای مورد دوم، rootBounds روی null تنظیم می‌شود تا از نشت داده‌ها در مبدأها جلوگیری شود.

IntersectionObserver درباره چه چیزی نیست؟

نکته‌ای که باید به‌خاطر داشته باشید این است که IntersectionObserver عمداً نه پیکسل کامل است و نه تأخیر کمی دارد. استفاده از آن‌ها برای پیاده‌سازی تلاش‌هایی مانند پویانمایی‌های وابسته به پیمایش قطعاً با شکست مواجه می‌شود، زیرا داده‌ها—به‌طور دقیق—تا زمانی که از آن‌ها استفاده کنید، قدیمی خواهند بود. توضیح‌دهنده جزئیات بیشتری درباره موارد استفاده اصلی برای IntersectionObserver دارد.

چه مقدار کار می‌توانم در فراخوانی برگشتی انجام دهم؟

کوتاه و شیرین: صرف زمان بیش‌ازحد در فراخوانی برگشتی باعث تأخیر در برنامه شما می‌شود—همه روش‌های معمول اعمال می‌شوند.

پیش بروید و عناصر خود را تلاقی دهید

پشتیبانی مرورگر از IntersectionObserver خوب است، زیرا در همه مرورگرهای نو دردسترس است. درصورت لزوم، می‌توان از شبیه‌ساز مرورگر در مرورگرهای قدیمی‌تر استفاده کرد و این شبیه‌ساز در مخزن WICG دردسترس است. بدیهی است که بااستفاده از آن شبیه‌ساز مرورگر، مزایای عملکردی را که پیاده‌سازی بومی به شما می‌دهد دریافت نخواهید کرد.

همین‌حالا می‌توانید استفاده از IntersectionObserver را شروع کنید! به ما بگویید چه چیزی به ذهنتان رسیده است.