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

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