IntersectionObservers की मदद से, यह पता चलता है कि निगरानी में रखा गया कोई एलिमेंट, ब्राउज़र के व्यूपोर्ट में कब आता है या उससे कब बाहर निकलता है.
मान लें कि आपको यह ट्रैक करना है कि आपके DOM में मौजूद कोई एलिमेंट, दिखने वाले व्यूपोर्ट में कब आता है. ऐसा इसलिए किया जा सकता है, ताकि इमेज को सही समय पर लेज़ी-लोड किया जा सके या आपको यह जानना हो कि उपयोगकर्ता किसी खास विज्ञापन बैनर को देख रहा है या नहीं. ऐसा करने के लिए, स्क्रोल इवेंट को हुक अप करें या समय-समय पर चलने वाले टाइमर का इस्तेमाल करके, उस एलिमेंट पर getBoundingClientRect()
को कॉल करें.
हालांकि, यह तरीका बहुत धीमा होता है, क्योंकि getBoundingClientRect()
को किया जाने वाला हर कॉल, ब्राउज़र को पूरे पेज को फिर से लेआउट करने के लिए मजबूर करता है और इससे आपकी वेबसाइट में काफ़ी जैंक पैदा होता है. जब आपको पता हो कि आपकी साइट किसी iframe में लोड हो रही है और आपको यह जानना हो कि उपयोगकर्ता को एलिमेंट कब दिखेगा, तो यह पता लगाना मुश्किल हो जाता है. सिंगल ऑरिजिन मॉडल और ब्राउज़र आपको उस वेब पेज से कोई भी डेटा ऐक्सेस नहीं करने देंगे जिसमें iframe है. यह समस्या, अक्सर iframes का इस्तेमाल करके लोड किए जाने वाले विज्ञापनों में होती है.
IntersectionObserver
को इसलिए डिज़ाइन किया गया था, ताकि विज्ञापन दिखने की जांच को ज़्यादा असरदार बनाया जा सके. यह सभी आधुनिक ब्राउज़र पर उपलब्ध है. IntersectionObserver
से आपको पता चलता है कि निगरानी में रखा गया कोई एलिमेंट, ब्राउज़र के व्यूपोर्ट में कब आता है या उससे कब बाहर निकलता है.
IntersectionObserver
बनाने का तरीका
एपीआई बहुत छोटा है और इसकी सबसे अच्छी जानकारी एक उदाहरण का इस्तेमाल करके दी गई है:
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
के लिए डिफ़ॉल्ट विकल्पों का इस्तेमाल करने पर, आपका कॉलबैक तब भी कॉल किया जाएगा, जब एलिमेंट आंशिक रूप से दिखेगा और जब वह व्यूपोर्ट से पूरी तरह बाहर निकल जाएगा.
अगर आपको एक से ज़्यादा एलिमेंट को निगरानी में रखना है, तो observe()
को कई बार कॉल करके, एक ही IntersectionObserver
इंस्टेंस का इस्तेमाल करके, एक से ज़्यादा एलिमेंट को निगरानी में रखा जा सकता है. ऐसा करना ज़रूरी है.
आपके कॉलबैक में 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()
का इस्तेमाल किया जाना चाहिए. इसका मतलब है कि आपके दिए गए कॉलबैक को कम प्राथमिकता दी गई है. ब्राउज़र, इसे तब कॉल करेगा, जब कोई गतिविधि न हो रही हो. यह डिज़ाइन से जुड़ा एक अहम फ़ैसला है.
स्क्रोलिंग डाइव
मुझे किसी एलिमेंट में स्क्रोल करने का शौक नहीं है, लेकिन मैं यहां किसी को जज करने के लिए नहीं हूं और न ही IntersectionObserver
. options
ऑब्जेक्ट में root
विकल्प होता है. इसकी मदद से, व्यूपोर्ट के बजाय किसी दूसरे ऑब्जेक्ट को रूट के तौर पर सेट किया जा सकता है. ध्यान रखें कि root
, निगरानी में रखे गए सभी एलिमेंट का पैरंट होना चाहिए.
सभी चीज़ों को इंटरसेक्शन करें!
नहीं! खराब डेवलपर! यह आपके उपयोगकर्ता के सीपीयू साइकल का सही इस्तेमाल नहीं है. उदाहरण के तौर पर, इनफ़ाइनाइट स्क्रोलर के बारे में सोचते हैं: इस स्थिति में, डीओएम में सेंटिनल जोड़ना और उनकी निगरानी (और रीसाइकल!) करना बिलकुल सही है. आपको अनलिमिटेड स्क्रोलर में आखिरी आइटम के पास सेंटिनल जोड़ना चाहिए. जब वह सेंटिनल दिखने लगे, तो डेटा लोड करने, अगले आइटम बनाने, उन्हें DOM से जोड़ने, और सेंटिनल को उसके हिसाब से फिर से पोज़िशन करने के लिए, कॉलबैक का इस्तेमाल किया जा सकता है. सेंटिनल को सही तरीके से रीसाइकल करने पर, observe()
को कोई और कॉल करने की ज़रूरत नहीं होती. IntersectionObserver
काम करता रहेगा.
ज़्यादा अपडेट, कृपया
जैसा कि पहले बताया गया है, कॉलबैक एक बार तब ट्रिगर होगा, जब मॉनिटर किया गया एलिमेंट पूरी तरह से व्यू में नहीं आता है और दूसरी बार, जब वह व्यूपोर्ट से बाहर निकल जाता है. इस तरह, IntersectionObserver
आपको इस सवाल का जवाब देता है, "क्या एलिमेंट X दिख रहा है?". हालांकि, हो सकता है कि कुछ मामलों में यह काफ़ी न हो.
ऐसे में, threshold
विकल्प का इस्तेमाल किया जा सकता है. इसकी मदद से, intersectionRatio
थ्रेशोल्ड का कलेक्शन तय किया जा सकता है. जब भी intersectionRatio
इनमें से किसी वैल्यू को पार करेगा, तब आपके कॉलबैक को कॉल किया जाएगा. threshold
की डिफ़ॉल्ट वैल्यू [0]
है, जो डिफ़ॉल्ट तरीके के बारे में बताती है. अगर हम threshold
को [0, 0.25, 0.5, 0.75, 1]
में बदलते हैं, तो हर बार जब एलिमेंट का एक चौथाई हिस्सा दिखेगा, तब हमें इसकी सूचना मिलेगी:
क्या कोई और विकल्प है?
फ़िलहाल, ऊपर दिए गए विकल्पों के अलावा सिर्फ़ एक और विकल्प है. rootMargin
की मदद से, रूट के मार्जिन तय किए जा सकते हैं. इससे इंटरसेक्शन के लिए इस्तेमाल किए जाने वाले एरिया को बड़ा या छोटा किया जा सकता है. इन मार्जिन को सीएसएस-स्टाइल स्ट्रिंग का इस्तेमाल करके तय किया जाता है, जैसे कि "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
का इस्तेमाल अभी से शुरू किया जा सकता है! हमें बताएं कि आपने क्या सोचा.