IntersectionObservers زمانی که یک عنصر مشاهده شده به نمای مرورگر وارد یا خارج می شود، به شما اطلاع می دهد.
فرض کنید می خواهید زمانی را که یک عنصر در 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
کنید! به ما بگویید چه چیزی به ذهنتان خطور کرد.