تتيح لك IntersectionObservers معرفة حالات دخول عنصر تمت ملاحظته إلى إطار عرض المتصفّح أو خروجه منه.
لنفترض أنك تريد تتبع وصول عنصر في نموذج العناصر في المستند (DOM) إلى إطار العرض المرئي. وننصحك بإجراء ذلك لتتمكّن من التحميل الكسول للصور في الوقت المناسب أو لأنّك بحاجة إلى معرفة ما إذا كان المستخدم يشاهد إعلان بانر معيّنًا. يمكنك إجراء ذلك من خلال تثبيت حدث الانتقال للأعلى أو للأسفل أو باستخدام موقّت دوري واستدعاء getBoundingClientRect()
.
حول هذا العنصر.
ومع ذلك، تكون هذه الطريقة بطيئة إلى حد كبير، حيث يفرض كل طلب إلى getBoundingClientRect()
على المتصفّح إعادة تخطيط الصفحة بأكملها، كما سيؤدي إلى تعليق موقعك الإلكتروني بشكل سلبي للغاية. تقترب المسائل القانونية من المستحيل عندما تعلم أنّه يتم تحميل موقعك الإلكتروني داخل إطار iframe وتريد معرفة الوقت الذي يمكن للمستخدم رؤية عنصر فيه. لن يسمح لك نموذج المصدر الفردي والمتصفّح بالوصول إلى أي بيانات من صفحة الويب التي تحتوي على إطار iframe. وهذه مشكلة شائعة في الإعلانات التي يتم تحميلها بشكل متكرّر على سبيل المثال باستخدام إطارات iframe.
إنّ جعل اختبار مستوى الظهور هذا أكثر كفاءة هو ما تم تصميم IntersectionObserver
، وتم توفيره في جميع المتصفحات الحديثة. يتيح لك IntersectionObserver
معرفة ما إذا يدخل عنصر تمت ملاحظته إلى إطار العرض في المتصفّح أو يخرج منه.
![إمكانية رؤية إطار iframe](https://web.developers.google.cn/static/articles/intersectionobserver/image/iframe-visibility-45640aaa99537.gif?authuser=5&hl=ar)
كيفية إنشاء 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
، سيتم استدعاء الدالة عندما يظهر العنصر بشكل جزئي أو عندما يغادر إطار العرض بالكامل.
إذا كنت بحاجة إلى ملاحظة عناصر متعددة، فمن الممكن ويُنصح بمراقبة عناصر متعددة باستخدام المثيل نفسه 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
ارتباطًا وثيقًا، ويُعلمك بمقدار العنصر المرئي. باستخدام هذه المعلومات، يمكنك الآن تنفيذ ميزات مثل تحميل مواد العرض في الوقت المناسب قبل أن تظهر على الشاشة. بفعالية.
![نسبة التقاطع.](https://web.developers.google.cn/static/articles/intersectionobserver/image/intersection-ratio-cc2e11cc70559.png?authuser=5&hl=ar)
تقدِّم IntersectionObserver
البيانات بشكلٍ غير متزامن، وسيتم تنفيذ رمز معاودة الاتصال في سلسلة المحادثات الرئيسية. بالإضافة إلى ذلك، تشير المواصفات إلى أنّ عمليات تنفيذ IntersectionObserver
يجب أن تستخدم requestIdleCallback()
. وهذا يعني أنّ الاتصال بمعاودة الاتصال التي تم تقديمها ذات أولوية منخفضة وسيتم إجراؤها من خلال المتصفح أثناء فترة عدم النشاط. هذا قرار تصميم واعٍ.
الانتقال للأسفل أو للأعلى
لستُ من المعجبين كثيرًا بالتمرير داخل أحد العناصر، ولكنني لست هنا للحكم، وكذلك IntersectionObserver
. يستخدم الكائن options
خيار root
الذي يتيح لك تحديد بديل لإطار العرض كجذر. من المهم أن تضع في اعتبارك أن root
يجب أن يكون أصلاً لجميع العناصر المرصودة.
اتقاطع مع كل الأشياء!
لا مطور سيئ. هذا ليس على دراية بدورات وحدة المعالجة المركزية (CPU) للمستخدم. لنلقِ نظرة على شريط التمرير اللا نهائي كمثال: في هذا السيناريو، من المستحسَن إضافة sentinel إلى DOM وملاحظة هذه العناصر (وإعادة تدويرها). يجب إضافة حارس بالقرب من العنصر الأخير في شريط التمرير اللانهائي. عندما يظهر هذا الحارس، يمكنك استخدام رد الاتصال لتحميل البيانات وإنشاء العناصر التالية وإرفاقها بنموذج العناصر في المستند (DOM) وإعادة ضبط موضع الحارس وفقًا لذلك. في حال إعادة تدوير الحارس بشكل صحيح، ليس هناك حاجة إلى إجراء مكالمة إضافية إلى observe()
. ما زالت "IntersectionObserver
" تعمل.
![شريط تمرير لا نهائي](https://web.developers.google.cn/static/articles/intersectionobserver/image/infinite-scroller-f23f2b90aa6bd.png?authuser=5&hl=ar)
يُرجى الاطّلاع على المزيد من الأخبار
كما ذكرنا سابقًا، سيتم تشغيل معاودة الاتصال مرة واحدة عندما يظهر العنصر الذي تمت ملاحظته جزئيًا عند ظهوره، ومرة أخرى عند مغادرة إطار العرض. بهذه الطريقة يقدم لك IntersectionObserver
إجابة على السؤال، "هل العنصر X ظاهر؟". وقد لا يكون ذلك كافيًا في بعض حالات الاستخدام.
وهنا يأتي دور خيار threshold
. وتسمح لك بتحديد مصفوفة من حدود intersectionRatio
. سيتم طلب معاودة الاتصال في كل مرة يتجاوز فيها intersectionRatio
إحدى هذه القيم. القيمة التلقائية للسمة threshold
هي [0]
، وهي تشرح السلوك التلقائي. إذا غيّرنا threshold
إلى [0, 0.25, 0.5, 0.75, 1]
، سنرسل إشعارًا في كل مرة يظهر فيها ربع إضافي من العنصر:
![صورة متحركة للعتبة.](https://web.developers.google.cn/static/articles/intersectionobserver/image/threshold-animation-818bf785c4e2d.gif?authuser=5&hl=ar)
هل لديك خيارات أخرى؟
حتى الآن، يتوفر خيار إضافي واحد فقط للحسابات المذكورة أعلاه. يتيح rootMargin
تحديد الهوامش للجذر، ما يتيح لك بشكل فعّال زيادة المساحة المستخدَمة للتقاطعات أو تصغيرها. يتم تحديد هذه الهوامش باستخدام سلسلة بنمط CSS، وهي á la "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. ومن الواضح أنك لن تحصل على مزايا الأداء باستخدام رمز polyfill هذا الذي توفره لك عملية التنفيذ المدمجة مع المحتوى.
يمكنك بدء استخدام "IntersectionObserver
" الآن. أخبرنا بما توصّلت إليه.