برنامج IntersectionObserver قيد العرض

تُعلمك IntersectionObservers عندما يدخل عنصر قيد المراقبة إلى إطار عرض المتصفّح أو يخرج منه.

توافق المتصفّح

  • Chrome: 51
  • Edge: 15.
  • Firefox: 55.
  • ‫Safari: 12.1

المصدر

لنفترض أنك تريد تتبع وصول عنصر في نموذج العناصر في المستند (DOM) إلى إطار العرض المرئي. قد تحتاج إلى إجراء ذلك حتى تتمكّن من تحميل الصور بشكل بطيء في الوقت المناسب أو لأنّك بحاجة إلى معرفة ما إذا كان المستخدم ينظر فعلاً إلى بانر إعلاني معيّن. يمكنك إجراء ذلك من خلال ربط حدث الانتقال للأعلى أو للأسفل أو باستخدام موقّت دوري واستدعاء getBoundingClientRect() على هذا العنصر.

ومع ذلك، فإنّ هذا الأسلوب بطيء جدًا لأنّ كلّ طلب إلى getBoundingClientRect() يفرض على المتصفّح إعادة ترتيب الصفحة بأكملها وسيؤدي إلى حدوث تقطُّع كبير في موقعك الإلكتروني. تقترب المسائل القانونية من المستحيل عندما تعلم أنّه يتم تحميل موقعك الإلكتروني داخل إطار iframe وتريد معرفة الوقت الذي يمكن للمستخدم رؤية عنصر فيه. لن يسمح لك نموذج المصدر الواحد والمتصفّح بالوصول إلى أي بيانات من صفحة الويب التي تحتوي على إطار iframe. هذه مشكلة شائعة في الإعلانات، على سبيل المثال، التي يتم تحميلها كثيرًا باستخدام إطارات iframe.

إنّ جعل اختبار مستوى الظهور هذا أكثر كفاءة هو ما تم تصميم IntersectionObserver، وتم توفيره في جميع المتصفحات الحديثة. يُعلمك مقياس IntersectionObserver عندما يدخل عنصر قيد المراقبة إلى إطار عرض المتصفّح أو يخرج منه.

مستوى ظهور إطار iframe

كيفية إنشاء 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 في المتصفحات القديمة وهو متاح في مستودع WICG. من الواضح أنّك لن تحصل على مزايا الأداء التي يوفّرها لك التنفيذ الأصلي باستخدام هذا العنصر البديل.

يمكنك بدء استخدام IntersectionObserver الآن. أخبِرنا بالحلّ الذي تمكّنت من الوصول إليه.