تُعلمك IntersectionObservers عندما يدخل عنصر قيد المراقبة إلى إطار عرض المتصفّح أو يخرج منه.
لنفترض أنّك تريد تتبُّع الحالات التي يدخل فيها عنصر في DOM إلى إطار العرض المرئي. قد تحتاج إلى إجراء ذلك حتى تتمكّن من تحميل الصور بشكل بطيء في الوقت المناسب أو لأنّك بحاجة إلى معرفة ما إذا كان المستخدم ينظر فعلاً إلى بانر إعلاني معيّن. يمكنك إجراء ذلك من خلال ربط حدث التمرير أو باستخدام موقّت دوري واستدعاء getBoundingClientRect()
على هذا العنصر.
ومع ذلك، فإنّ هذا النهج بطيء جدًا لأنّ كلّ طلب إلى getBoundingClientRect()
يفرض على المتصفّح إعادة ترتيب الصفحة بأكملها وسيؤدي إلى حدوث تقطُّع كبير في موقعك الإلكتروني. تصبح الأمور شبه مستحيلة عندما يكون موقعك الإلكتروني يتم تحميله داخل إطار iframe وتريد معرفة متى يمكن للمستخدم رؤية عنصر معيّن. لن يسمح لك نموذج المصدر الواحد والمتصفّح بالوصول إلى أي بيانات من صفحة الويب التي تحتوي على إطار iframe. هذه مشكلة شائعة في الإعلانات، على سبيل المثال، التي يتم تحميلها كثيرًا باستخدام إطارات iframe.
تم تصميم 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
، سيتمّ استدعاء الدالة المُعاد الاتصال بها عند ظهور العنصر جزئيًا في العرض وعند خروجه بالكامل من إطار العرض.
إذا كنت بحاجة إلى مراقبة عناصر متعدّدة، من الممكن وننصح بمراقبة عناصر متعدّدة باستخدام مثيل 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()
. وهذا يعني أنّ طلب ردّ الاتصال المقدَّم منك له أولوية منخفضة وسيجريه المتصفّح خلال وقت السكون. هذا قرار تصميم مدروس.
أقسام div التي يمكن التمرير فيها
لست من محبّي الانتقال داخل العنصر، ولكنّني لست هنا لأحكم على ذلك، ولا يفعل ذلك 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
Not؟
يُرجى العِلم أنّ IntersectionObserver
لا يقدّم جودة دقة بكسل مثالية أو وقت استجابة منخفضًا عن قصد. ومن المؤكد أنّ استخدامها لتنفيذ مشاريع مثل الصور المتحركة التي تعتمد على الانتقال إلى الأسفل أو للأعلى سيؤدي إلى الفشل، لأنّ البيانات ستكون قديمة بحلول الوقت الذي ستتمكن فيه من استخدامها. يتضمّن الشرح المزيد من التفاصيل حول حالات الاستخدام الأصلية لـ IntersectionObserver
.
ما هو حجم العمل الذي يمكنني تنفيذه في المكالمة المُعاد توجيهها؟
نصيحة موجزة: سيؤدي قضاء وقت طويل في طلب إعادة الاتصال إلى تأخُّر تطبيقك، وينطبق ذلك على جميع الممارسات الشائعة.
اذهب إلى أبعد الحدود واجعل عناصرك تتداخل.
إنّ توافق IntersectionObserver
مع المتصفّحات جيد، لأنّه متاح في جميع المتصفحات الحديثة. إذا لزم الأمر، يمكن استخدام polyfill في المتصفّحات القديمة، وهو متوفّر في مستودع Web Compatability Group (WICG). من الواضح أنّك لن تحصل على مزايا الأداء التي يوفّرها لك التنفيذ الأصلي باستخدام هذا العنصر البديل.
يمكنك بدء استخدام IntersectionObserver
الآن. أخبِرنا بالحلّ الذي تمكّنت من الوصول إليه.