IntersectionObserver در حال مشاهده است

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

پشتیبانی مرورگر

  • کروم: 51.
  • لبه: 15.
  • فایرفاکس: 55.
  • سافاری: 12.1.

منبع

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

با این حال، این رویکرد به طرز دردناکی کند است زیرا هر فراخوانی به getBoundingClientRect() مرورگر را مجبور می‌کند کل صفحه را مجدداً طرح‌بندی کند و jank قابل توجهی را به وب‌سایت شما معرفی می‌کند. وقتی می‌دانید سایت شما در داخل یک iframe بارگذاری می‌شود و می‌خواهید بدانید کاربر چه زمانی می‌تواند یک عنصر را ببیند، مسائل تقریبا غیرممکن می‌شوند. مدل Single Origin و مرورگر به شما اجازه دسترسی به هیچ داده ای از صفحه وب حاوی iframe را نمی دهند. این یک مشکل رایج برای تبلیغاتی است که اغلب با استفاده از iframe بارگذاری می شوند.

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

قابلیت مشاهده آی فریم

نحوه ایجاد 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 ، پاسخ تماس شما هم زمانی که عنصر به طور جزئی در معرض دید قرار می‌گیرد و هم زمانی که به طور کامل از viewport خارج می‌شود، فراخوانی می‌شود.

اگر نیاز به مشاهده چندین عنصر دارید، مشاهده چندین عنصر با استفاده از یک نمونه 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() بر روی عنصر ریشه است که به طور پیش فرض viewport است. boundingClientRect نتیجه getBoundingClientRect() بر روی عنصر مشاهده شده فراخوانی شده است. intersectionRect محل تلاقی این دو مستطیل است و به طور موثر به شما می گوید کدام قسمت از عنصر مشاهده شده قابل مشاهده است. intersectionRatio ارتباط نزدیکی با هم دارد و به شما می گوید چه مقدار از عنصر قابل مشاهده است. با در اختیار داشتن این اطلاعات، اکنون می توانید ویژگی هایی مانند بارگیری به موقع دارایی ها را قبل از اینکه روی صفحه قابل مشاهده شوند، پیاده سازی کنید. کارآمد.

نسبت تقاطع.

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

دیوی اسکرول

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

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

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

اسکرول بی نهایت

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

همانطور که قبلاً ذکر شد، زمانی که عنصر مشاهده شده به طور جزئی در معرض دید قرار می گیرد، تماس برگشتی یک بار راه اندازی می شود و بار دیگر هنگامی که از viewport خارج می شود. به این ترتیب 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 دارد.

چه مقدار کار می توانم در پاسخ به تماس انجام دهم؟

Short 'n Sweet: صرف زمان زیاد در پاسخ به تماس، برنامه شما را با تاخیر مواجه می‌کند—همه روش‌های رایج اعمال می‌شوند.

برو جلو و عناصرت را قطع کن

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

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