تحريك العناصر أثناء التمرير باستخدام الرسوم المتحركة المستندة إلى التمرير

تعرَّف على كيفية استخدام "المخططات الزمنية للتمرير" و"المخططات الزمنية للعرض" لإنشاء صور متحركة مستندة إلى التمرير بطريقة تعريفية.

تاريخ النشر: 5 مايو 2023

الصور المتحركة المستندة إلى التمرير

Browser Support

  • Chrome: 115.
  • Edge: 115.
  • Firefox: behind a flag.
  • Safari: 26.

Source

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

مؤشر قراءة في أعلى المستند، يتم التحكّم فيه من خلال التمرير.

هناك نوع مشابه من الصور المتحركة المستندة إلى التمرير، وهو صورة متحركة مرتبطة بموضع عنصر ضمن حاوية التمرير. باستخدامها، يمكن مثلاً أن تتلاشى العناصر تدريجيًا عند ظهورها على الشاشة.

تظهر الصور على هذه الصفحة تدريجيًا عند عرضها.

الطريقة التقليدية لتحقيق هذه الأنواع من التأثيرات هي الاستجابة لأحداث التمرير على سلسلة التعليمات الرئيسية، ما يؤدي إلى مشكلتين رئيسيتين:

  • تنفّذ المتصفّحات الحديثة عملية التمرير في عملية منفصلة، وبالتالي يتم عرض أحداث التمرير بشكل غير متزامن.
  • تكون الصور المتحركة في سلسلة التعليمات الرئيسية عرضةً لعدم سلاسة العرض.

ويجعل ذلك إنشاء صور متحركة فعّالة تعتمد على التمرير وتتزامن معه أمرًا مستحيلاً أو صعبًا للغاية.

بدءًا من الإصدار 115 من Chrome، تتوفّر مجموعة جديدة من واجهات برمجة التطبيقات والمفاهيم التي يمكنك استخدامها لتفعيل الرسوم المتحركة المستندة إلى التمرير بشكل تصريحي: "المخططات الزمنية للتمرير" و"المخططات الزمنية للعرض".

تتكامل هذه المفاهيم الجديدة مع Web Animations API (WAAPI) وCSS Animations API الحاليَين، ما يسمح لها بالاستفادة من المزايا التي توفّرها واجهات برمجة التطبيقات الحالية هذه. ويشمل ذلك إمكانية تشغيل الرسوم المتحركة المستندة إلى التمرير خارج سلسلة التعليمات الرئيسية. نعم، يمكنك الآن الحصول على رسوم متحركة سلسة للغاية، يتم تشغيلها من خلال التمرير، خارج سلسلة التعليمات الرئيسية، وذلك باستخدام بضعة أسطر فقط من الرموز البرمجية الإضافية. ما الذي لا يعجبك فيها؟

لمحة سريعة عن الصور المتحركة على الويب

الصور المتحركة على الويب باستخدام CSS

لإنشاء حركة في CSS، حدِّد مجموعة من الإطارات الرئيسية باستخدام قاعدة @keyframes. اربطها بعنصر باستخدام السمة animation-name مع ضبط animation-duration لتحديد المدة التي يجب أن تستغرقها الحركة. تتوفّر المزيد من خصائص animation-* الكتابة الكاملة، مثل animation-easing-function وanimation-fill-mode على سبيل المثال لا الحصر، ويمكن دمجها كلها في animation الكتابة المختصرة.

على سبيل المثال، إليك صورة متحركة توسّع عنصرًا على المحور X مع تغيير لون الخلفية أيضًا:

@keyframes scale-up {
  from {
    background-color: red;
    transform: scaleX(0);
  }
  to {
    background-color: darkred;
    transform: scaleX(1);
  }
}

#progressbar {
  animation: 2.5s linear forwards scale-up;
}

الصور المتحركة على الويب باستخدام JavaScript

في JavaScript، يمكن استخدام Web Animations API لتحقيق النتيجة نفسها بالضبط. يمكنك إجراء ذلك إما عن طريق إنشاء مثيلات جديدة من Animation وKeyFrameEffect، أو استخدام طريقة Element animate() الأقصر بكثير.

document.querySelector('#progressbar').animate(
  {
    backgroundColor: ['red', 'darkred'],
    transform: ['scaleX(0)', 'scaleX(1)'],
  },
  {
    duration: 2500,
    fill: 'forwards',
    easing: 'linear',
   }
);

تتشابه هذه النتيجة المرئية لمقتطف JavaScript أعلاه مع إصدار CSS السابق.

المخطّطات الزمنية للصور المتحركة

بشكلٍ تلقائي، يتم تشغيل رسم متحرك مرفق بعنصر ما على الجدول الزمني للمستند. يبدأ وقت إنشائه من 0 عند تحميل الصفحة، ويبدأ في التقدّم مع تقدّم الوقت الفعلي. هذا هو المخطط الزمني التلقائي للرسوم المتحركة، وكان حتى الآن المخطط الزمني الوحيد الذي يمكنك الوصول إليه.

يحدّد مواصفات الحركات المستندة إلى التمرير نوعَين جديدَين من المخططات الزمنية يمكنك استخدامهما:

  • المخطط الزمني لتقدّم التمرير: مخطط زمني مرتبط بموضع التمرير في حاوية تمرير على طول محور معيّن.
  • عرض المخطط الزمني للتقدّم: مخطط زمني مرتبط بالموضع النسبي لعنصر معيّن ضمن حاوية التمرير الخاصة به

مخطط زمني لمستوى التقدّم في التمرير

المخطط الزمني لتقدّم التمرير هو مخطط زمني للرسوم المتحركة مرتبط بتقدّم موضع التمرير في حاوية تمرير، ويُعرف أيضًا باسم منفذ التمرير أو أداة التمرير على طول محور معيّن. تحوّل هذه السمة موضعًا في نطاق التمرير إلى نسبة مئوية من مستوى التقدّم.

يمثّل موضع التمرير للأعلى أو للأسفل في البداية نسبة% 0 من مستوى التقدّم، ويمثّل موضع التمرير للأعلى أو للأسفل في النهاية نسبة% 100 من مستوى التقدّم. في التمثيل المرئي التالي، يمكنك ملاحظة أنّ عدد مرات الظهور يزداد من% 0 إلى% 100 أثناء تمرير شريط التمرير من أعلى إلى أسفل.

تمثيل مرئي للمخطّط الزمني لمستوى التقدّم في التمرير أثناء الانتقال للأسفل إلى نهاية شريط التمرير، تزداد قيمة مستوى التقدّم من 0% إلى 100%.

✨ جرِّب الميزة بنفسك

يتم غالبًا اختصار "المخطط الزمني لتقدّم التمرير" إلى "مخطط زمني للتمرير".

عرض المخطط الزمني لمستوى التقدّم

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

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

يبدأ "المخطط الزمني لتقدّم العرض" من اللحظة التي يبدأ فيها عنصر ما في التقاطع مع أداة التمرير وينتهي عندما يتوقف العنصر عن التقاطع مع أداة التمرير. في التمثيل المرئي التالي، يمكنك أن ترى أنّ عدّاد التقدّم يبدأ من 0% عندما يدخل العنصر حاوية التمرير ويصل إلى% 100 في اللحظة التي يغادر فيها العنصر حاوية التمرير.

تمثّل هذه الصورة مخططًا زمنيًا لمستوى تقدّم العرض. يتم احتساب مستوى التقدّم من 0% إلى 100% عندما يعبر العنصر (المربّع الأخضر) شريط التمرير.

✨ جرِّب الميزة بنفسك

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

الاستفادة من المخططات الزمنية لتقدّم التمرير

إنشاء مخطط زمني مجهول الهوية لتقدّم التمرير في CSS

أسهل طريقة لإنشاء "مخطط زمني للتمرير" في CSS هي استخدام الدالة scroll(). يؤدي ذلك إلى إنشاء "مخطط زمني للتمرير" مجهول الهوية يمكنك ضبطه كقيمة للسمة الجديدة animation-timeline.

مثال:

@keyframes animate-it {  }

.subject {
  animation: animate-it linear;
  animation-timeline: scroll(root block);
}

تقبل الدالة scroll() الوسيطتين <scroller> و<axis>.

القيم المقبولة للوسيطة <scroller> هي ما يلي:

  • nearest: تستخدم حاوية التمرير الأقرب إلى العنصر (الإعداد التلقائي).
  • root: تستخدم إطار عرض المستند كحاوية التمرير.
  • self: تستخدم العنصر نفسه كحاوية تمرير.

القيم المقبولة للوسيطة <axis> هي ما يلي:

  • block: تستخدم مقياس التقدّم على طول محور الحظر لحاوية التمرير (القيمة التلقائية).
  • inline: تستخدِم مقياس التقدّم على طول المحور المضمّن لحاوية التمرير.
  • y: تستخدم مقياس التقدّم على طول المحور y لحاوية التمرير.
  • x: تستخدِم مقياس التقدّم على طول المحور x لحاوية التمرير.

على سبيل المثال، لربط رسم متحرك بأداة التمرير الرئيسية على محور الكتلة، تكون القيم التي يجب تمريرها إلى scroll() هي root وblock. وبالتالي، تكون القيمة scroll(root block).

عرض توضيحي: مؤشر تقدُّم القراءة

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

العرض التوضيحي: مؤشر تقدّم القراءة.

✨ جرِّب الميزة بنفسك

يتم وضع مؤشر تقدُّم القراءة في أعلى الصفحة باستخدام الموضع الثابت. للاستفادة من الحركات المركّبة، لا يتم تحريك width، بل يتم تصغير العنصر على المحور x باستخدام transform.

<body>
  <div id="progress"></div>
  …
</body>
@keyframes grow-progress {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}

#progress {
  position: fixed;
  left: 0; top: 0;
  width: 100%; height: 1em;
  background: red;

  transform-origin: 0 50%;
  animation: grow-progress auto linear;
  animation-timeline: scroll();
}

تم ضبط المخطط الزمني للحركة grow-progress على العنصر #progress على مخطط زمني مجهول الهوية تم إنشاؤه باستخدام scroll(). لم يتم تقديم أي وسيطات إلى scroll()، لذا سيتم استخدام القيم التلقائية.

إنّ أداة التمرير التلقائية التي يتم تتبُّعها هي nearest، والمحور التلقائي هو block. يستهدف ذلك بشكل فعّال أداة التمرير الرئيسية لأنّها أداة التمرير الأقرب لعنصر #progress، مع تتبُّع اتجاه الحظر.

إنشاء مخطط زمني مُسمّى لتقدّم التمرير في CSS

هناك طريقة بديلة لتحديد "المخطط الزمني لتقدّم التمرير" وهي استخدام مخطط زمني مسمّى. قد يكون هذا الخيار أكثر تفصيلاً، ولكنّه قد يكون مفيدًا عندما لا تستهدف أداة تمرير رئيسية أو أداة تمرير جذرية، أو عندما تستخدم الصفحة جداول زمنية متعددة أو عندما لا تعمل عمليات البحث التلقائي. بهذه الطريقة، يمكنك التعرّف على "المخطط الزمني لتقدّم التمرير" من خلال الاسم الذي تمنحه له.

لإنشاء "المخطط الزمني لتقدّم التمرير" باسم معيّن على أحد العناصر، اضبط السمة scroll-timeline-name في CSS على حاوية التمرير على معرّف من اختيارك. يجب أن تبدأ القيمة بـ --.

لتعديل المحور الذي تريد تتبُّعه، عليك أيضًا تحديد السمة scroll-timeline-axis. القيم المسموح بها هي نفسها القيم المسموح بها في الوسيطة <axis> للدالة scroll().

أخيرًا، لربط الحركة بالجدول الزمني لتقدّم التمرير، اضبط السمة animation-timeline في العنصر الذي يجب تحريكه على القيمة نفسها المستخدَمة في المعرّف scroll-timeline-name.

مثال على الرمز البرمجي:

@keyframes animate-it {  }

.scroller {
  scroll-timeline-name: --my-scroller;
  scroll-timeline-axis: inline;
}

.scroller .subject {
  animation: animate-it linear;
  animation-timeline: --my-scroller;
}

يمكنك الجمع بين scroll-timeline-name وscroll-timeline-axis في الاختصار scroll-timeline إذا أردت ذلك. على سبيل المثال:

scroll-timeline: --my-scroller inline;

يتضمّن هذا العرض التوضيحي مؤشرًا للخطوات يظهر فوق كل لوحة عرض دوّارة للصور. عندما يحتوي الرف الدائري على ثلاث صور، يبدأ شريط المؤشر بعرض 33% من العرض للإشارة إلى أنّك تشاهد حاليًا الصورة الأولى من ثلاث صور. عندما تكون الصورة الأخيرة ظاهرة (يتم تحديد ذلك من خلال انتقال أداة التمرير إلى النهاية)، يشغل المؤشر العرض الكامل لأداة التمرير. يتم استخدام "المخطط الزمني لتقدّم التمرير" المسمّى لتشغيل الصورة المتحركة.

العرض التوضيحي: مؤشر الخطوات في لوحة العرض الدوّارة الأفقية.

✨ جرِّب الميزة بنفسك

في ما يلي الترميز الأساسي لمعرض الصور:

<div class="gallery" style="--num-images: 2;">
  <div class="gallery__scrollcontainer">
    <div class="gallery__progress"></div>
    <div class="gallery__entry">…</div>
    <div class="gallery__entry">…</div>
  </div>
</div>

يتم تحديد موضع العنصر .gallery__progress بشكل مطلق ضمن العنصر الحاوي .gallery. يتم تحديد حجمها الأولي من خلال السمة المخصّصة --num-images.

.gallery {
  position: relative;
}


.gallery__progress {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 1em;
  transform: scaleX(calc(1 / var(--num-images)));
}

يضع .gallery__scrollcontainer عناصر .gallery__entry المضمّنة أفقيًا وهو العنصر الذي يتم تمريره. من خلال تتبُّع موضع التمرير، يتم تحريك .gallery__progress. يتم ذلك من خلال الرجوع إلى المخطط الزمني المسمّى "مقياس تقدّم التمرير" --gallery__scrollcontainer.

@keyframes grow-progress {
  to { transform: scaleX(1); }
}

.gallery__scrollcontainer {
  overflow-x: scroll;
  scroll-timeline: --gallery__scrollcontainer inline;
}
.gallery__progress {
  animation: auto grow-progress linear forwards;
  animation-timeline: --gallery__scrollcontainer;
}

إنشاء مخطط زمني لتقدّم التمرير باستخدام JavaScript

لإنشاء "مخطط زمني للتمرير" في JavaScript، أنشئ مثيلاً جديدًا لفئة ScrollTimeline. مرِّر حزمة سمات تتضمّن source وaxis اللذين تريد تتبُّعهما.

  • source: مرجع إلى العنصر الذي تريد تتبُّع أداة التمرير الخاصة به. استخدِم document.documentElement لاستهداف أداة التمرير الجذرية.
  • axis: تحدّد هذه السمة المحور المطلوب تتبُّعه. على غرار صيغة CSS، القيم المقبولة هي block وinline وx وy.
const tl = new ScrollTimeline({
  source: document.documentElement,
});

لإرفاقها بـ Web Animation، مرِّرها كخاصية timeline واحذف أي duration إذا كان هناك أي منها.

$el.animate({
  opacity: [0, 1],
}, {
  timeline: tl,
});

عرض توضيحي: مؤشر تقدّم القراءة، إعادة النظر

لإعادة إنشاء مؤشر تقدّم القراءة باستخدام JavaScript، مع استخدام الترميز نفسه، استخدِم رمز JavaScript التالي:

const $progressbar = document.querySelector('#progress');

$progressbar.style.transformOrigin = '0% 50%';
$progressbar.animate(
  {
    transform: ['scaleX(0)', 'scaleX(1)'],
  },
  {
    fill: 'forwards',
    timeline: new ScrollTimeline({
      source: document.documentElement,
    }),
  }
);

النتيجة المرئية مماثلة في إصدار CSS: يتتبّع العنصر timeline الذي تم إنشاؤه أداة التمرير الرئيسية ويغيّر حجم العنصر #progress على المحور x من% 0 إلى% 100 أثناء تمرير الصفحة.

✨ جرِّب الميزة بنفسك

الاستفادة من "المخطط الزمني لمستوى التقدّم"

إنشاء مخطط زمني لتقدّم المشاهدة بدون الكشف عن الهوية في CSS

لإنشاء "مخطط زمني لتقدّم المشاهدة"، استخدِم الدالة view(). الوسيطتان المقبولتان هما <axis> و<view-timeline-inset>.

  • <axis> هو نفسه الذي يظهر في المخطط الزمني لتقدّم التمرير ويحدّد المحور الذي يجب تتبّعه. القيمة التلقائية هي block.
  • باستخدام <view-timeline-inset>، يمكنك تحديد إزاحة (موجبة أو سالبة) لتعديل الحدود عند اعتبار أحد العناصر معروضًا أو غير معروض. يجب أن تكون القيمة نسبة مئوية أو auto، مع العلم أنّ auto هي القيمة التلقائية.

على سبيل المثال، لربط حركة بعنصر يتقاطع مع أداة التمرير الخاصة به على محور الكتلة، استخدِم view(block). على غرار scroll()، اضبط هذه القيمة كقيمة للسمة animation-timeline، ولا تنسَ ضبط animation-duration على auto.

باستخدام الرمز التالي، سيظهر كل img تدريجيًا أثناء انتقاله عبر نافذة العرض أثناء التمرير.

@keyframes reveal {
  from { opacity: 0; }
  to { opacity: 1; }
}

img {
  animation: reveal linear;
  animation-timeline: view();
}

استراحة: عرض نطاقات المخطط الزمني

بشكلٍ تلقائي، يتم ربط حركة مرتبطة بالمخطط الزمني للعرض بنطاق المخطط الزمني بأكمله. يبدأ هذا الإجراء من اللحظة التي يكون فيها العنصر على وشك الدخول إلى منفذ التمرير وينتهي عندما يغادر العنصر منفذ التمرير بالكامل.

يمكن أيضًا ربطها بجزء معيّن من "المخطط الزمني للعرض" من خلال تحديد النطاق الذي يجب إرفاقها به. يمكن أن يحدث ذلك، على سبيل المثال، فقط عندما يدخل الموضوع إلى أداة التمرير. في التمثيل المرئي التالي، يبدأ احتساب مستوى التقدّم من% 0 عندما يدخل العنصر حاوية التمرير، ولكنّه يصل إلى% 100 من اللحظة التي يتقاطع فيها بالكامل.

مخطط زمني للعرض تم ضبطه لتتبُّع نطاق إدخال الموضوع. لا يتم تشغيل الحركة إلا أثناء دخول العنصر إلى إطار العرض.

في ما يلي النطاقات المحتملة لـ "مخطط المشاهدة الزمني" التي يمكنك استهدافها:

  • cover: يمثّل النطاق الكامل للمخطط الزمني لمستوى تقدّم المشاهدة.
  • entry: يمثّل النطاق الذي يدخل خلاله المربّع الرئيسي إلى نطاق إمكانية ظهور مستوى تقدّم العرض.
  • exit: يمثّل النطاق الذي يخرج خلاله المربع الرئيسي من نطاق إمكانية رؤية تقدّم المشاهدة.
  • entry-crossing: يمثّل النطاق الذي يعبر خلاله المربع الرئيسي حافة الحد النهائي.
  • exit-crossing: يمثّل النطاق الذي يعبر خلاله المربّع الرئيسي حافة حدود البداية.
  • contain: يمثّل النطاق الذي يكون فيه المربّع الرئيسي إما مضمّنًا بالكامل في نطاق ظهور مستوى تقدّم العرض ضمن منفذ التمرير أو يغطّيه بالكامل. يعتمد ذلك على ما إذا كان العنصر أطول أو أقصر من أداة التمرير.

لتحديد نطاق، يجب ضبط بداية ونهاية النطاق. يتكوّن كلّ منهما من اسم النطاق (راجِع القائمة أعلاه) وإزاحة النطاق لتحديد الموضع ضمن اسم النطاق هذا. عادةً ما تكون قيمة الإزاحة عن النطاق نسبة مئوية تتراوح بين 0% و100%، ولكن يمكنك أيضًا تحديد طول ثابت، مثل 20em.

على سبيل المثال، إذا أردت تشغيل حركة من لحظة دخول أحد الأشخاص إلى المشهد، اختَر entry 0% كنقطة بداية النطاق. لإنهاء العملية قبل دخول الموضوع، اختَر entry 100% كقيمة لنهاية النطاق.

في CSS، يمكنك ضبط ذلك باستخدام السمة animation-range. مثال:

animation-range: entry 0% entry 100%;

في JavaScript، استخدِم السمتَين rangeStart وrangeEnd.

$el.animate(
  keyframes,
  {
    timeline: tl,
    rangeStart: 'entry 0%',
    rangeEnd: 'entry 100%',
  }
);

استخدِم الأداة المضمّنة أدناه لمعرفة ما يمثّله كل اسم نطاق وكيف تؤثّر النسب المئوية في موضعَي البدء والانتهاء. حاوِل ضبط بداية النطاق على entry 0% ونهاية النطاق على cover 50%، ثم اسحب شريط التمرير للاطّلاع على نتيجة الحركة.

أداة "عرض نطاقات المخطّط الزمني"، متاحة على https://goo.gle/view-timeline-range-tool

مشاهدة تسجيل

أثناء تجربة أدوات "نطاقات المخطط الزمني للعرض"، قد تلاحظ أنّه يمكن استهداف بعض النطاقات من خلال مجموعتَين مختلفتَين من "اسم النطاق" + "إزاحة النطاق". على سبيل المثال، تستهدف entry 0% وentry-crossing 0% وcover 0% المنطقة نفسها.

عندما يستهدف range-start وrange-end اسم النطاق نفسه ويمتدان على النطاق بأكمله، من% 0 إلى %100، يمكنك اختصار القيمة إلى اسم النطاق فقط. على سبيل المثال، يمكن إعادة كتابة animation-range: entry 0% entry 100%; إلى animation-range: entry الأقصر بكثير.

العرض التوضيحي: كشف الصورة

يعرض هذا العرض التوضيحي الصور بشكل تدريجي عند دخولها إلى نافذة التمرير. يتم ذلك باستخدام "المخطط الزمني للعرض المخفي الهوية". تم تعديل نطاق الرسوم المتحركة بحيث تكون كل صورة في مستوى التعتيم الكامل عندما تكون في منتصف أداة التمرير.

العرض التوضيحي: كشف الصورة

✨ جرِّب الميزة بنفسك

يتم تحقيق تأثير التوسيع باستخدام clip-path متحرك. في ما يلي رمز CSS المستخدَم لهذا التأثير:

@keyframes reveal {
  from { opacity: 0; clip-path: inset(0% 60% 0% 50%); }
  to { opacity: 1; clip-path: inset(0% 0% 0% 0%); }
}

.revealing-image {
  animation: auto linear reveal both;
  animation-timeline: view();
  animation-range: entry 25% cover 50%;
}

إنشاء "مخطط زمني لتقدّم المشاهدة" مُسمّى في CSS

كما هو الحال مع "المخططات الزمنية للتمرير" التي تتضمّن نُسخًا مُسَمّاة، يمكنك أيضًا إنشاء "مخططات زمنية للعرض" مُسَمّاة. بدلاً من السمات scroll-timeline-*، يمكنك استخدام خيارات منتج تتضمّن البادئة view-timeline-، أي view-timeline-name وview-timeline-axis.

وينطبق النوع نفسه من القيم والقواعد نفسها للبحث عن مخطط زمني مسمّى.

العرض التوضيحي: كشف الصورة، إعادة النظر

بعد إعادة صياغة العرض التوضيحي لظهور الصورة من وقت سابق، يبدو الرمز المعدَّل على النحو التالي:

.revealing-image {
  view-timeline-name: --revealing-image;
  view-timeline-axis: block;

  animation: auto linear reveal both;
  animation-timeline: --revealing-image;
  animation-range: entry 25% cover 50%;
}

باستخدام view-timeline-name: revealing-image، سيتم تتبُّع العنصر ضمن أداة التمرير الأقرب إليه. بعد ذلك، يتم استخدام القيمة نفسها كقيمة للسمة animation-timeline. ستكون النتيجة المرئية مماثلة تمامًا لما كانت عليه في السابق.

✨ جرِّب الميزة بنفسك

إنشاء مخطّط زمني لعرض التقدّم في JavaScript

لإنشاء "مخطط زمني للعرض" في JavaScript، أنشئ مثيلاً جديدًا لفئة ViewTimeline. مرِّر حزمة سمات تتضمّن subject التي تريد تتبُّعها وaxis وinset.

  • subject: مرجع إلى العنصر الذي تريد تتبُّعه ضمن أداة التمرير الخاصة به
  • axis: تمثّل هذه السمة المحور الذي سيتم تتبُّعه. على غرار صيغة CSS، القيم المقبولة هي block وinline وx وy.
  • inset: تعديل (موجب) أو (سالب) في موضع الإدراج لمنطقة العرض عند تحديد ما إذا كان المربّع معروضًا.
const tl = new ViewTimeline({
  subject: document.getElementById('subject'),
});

لإرفاقها بـ Web Animation، مرِّرها كخاصية timeline واحذف أي duration إذا كان هناك أي منها. يمكنك اختياريًا إدخال معلومات النطاق باستخدام السمتَين rangeStart وrangeEnd.

$el.animate({
  opacity: [0, 1],
}, {
  timeline: tl,
  rangeStart: 'entry 25%',
  rangeEnd: 'cover 50%',
});

✨ جرِّب الميزة بنفسك

المزيد من الأنشطة المقترَحة

ربطها بنطاقات "مخطط زمني للعرض" متعددة باستخدام مجموعة واحدة من الإطارات الرئيسية

لنلقِ نظرة على هذا العرض التوضيحي لقائمة جهات الاتصال حيث يتم تحريك إدخالات القائمة. عندما يظهر إدخال في القائمة في منفذ العرض من الأسفل، يتم تمريره سريعًا مع التلاشي تدريجيًا، وعندما يخرج من منفذ العرض من الأعلى، يتم تمريره سريعًا مع التلاشي تدريجيًا.

العرض التوضيحي: قائمة جهات الاتصال

✨ جرِّب الميزة بنفسك

في هذا العرض التوضيحي، يتم تزيين كل عنصر بمخطط زمني واحد للعرض يتتبّع العنصر أثناء عبوره لمنطقة التمرير، ولكن يتم ربط رسمَين متحرّكَين مستندَين إلى التمرير به. يتم ربط الحركة animate-in بالنطاق entry من المخطط الزمني، والحركة animate-out بالنطاق exit من المخطط الزمني.

@keyframes animate-in {
  0% { opacity: 0; transform: translateY(100%); }
  100% { opacity: 1; transform: translateY(0); }
}
@keyframes animate-out {
  0% { opacity: 1; transform: translateY(0); }
  100% { opacity: 0; transform: translateY(-100%); }
}

#list-view li {
  animation: animate-in linear forwards,
             animate-out linear forwards;
  animation-timeline: view();
  animation-range: entry, exit;
}

بدلاً من تشغيل صورتَين متحركتَين مختلفتَين مرتبطتَين بنطاقَين مختلفَين، يمكن أيضًا إنشاء مجموعة واحدة من إطارات المفاتيح التي تحتوي على معلومات النطاق.

@keyframes animate-in-and-out {
  entry 0%  {
    opacity: 0; transform: translateY(100%);
  }
  entry 100%  {
    opacity: 1; transform: translateY(0);
  }
  exit 0% {
    opacity: 1; transform: translateY(0);
  }
  exit 100% {
    opacity: 0; transform: translateY(-100%);
  }
}

#list-view li {
  animation: linear animate-in-and-out;
  animation-timeline: view();
}

بما أنّ الإطارات الرئيسية تحتوي على معلومات النطاق، ليس عليك تحديد animation-range. والنتيجة هي نفسها تمامًا كما كانت من قبل.

✨ جرِّب الميزة بنفسك

الربط بمخطط زمني غير مرتبط بعنصر Scroll

يقتصر آلية البحث عن "المخططات الزمنية للتمرير" و"المخططات الزمنية للعرض" المُسَمّاة على العناصر الرئيسية القابلة للتمرير فقط. في كثير من الأحيان، لا يكون العنصر الذي يجب تحريكه عنصرًا ثانويًا للعنصر الذي يجب تتبّعه.

لكي تعمل هذه الميزة، يجب استخدام السمة timeline-scope. يمكنك استخدام هذه السمة لتعريف مخطط زمني بهذا الاسم بدون إنشائه فعليًا. يمنح ذلك المخطط الزمني الذي يحمل هذا الاسم نطاقًا أوسع. من الناحية العملية، يمكنك استخدام السمة timeline-scope على عنصر رئيسي مشترك لكي يتم ربط المخطط الزمني لأداة التمرير الفرعية به.

على سبيل المثال:

.parent {
  timeline-scope: --tl;
}
.parent .scroller {
  scroll-timeline: --tl;
}
.parent .scroller ~ .subject {
  animation: animate linear;
  animation-timeline: --tl;
}

في هذه المقتطفة:

  • يعرّف العنصر .parent مخططًا زمنيًا بالاسم --tl. ويمكن لأي عنصر فرعي العثور عليه واستخدامه كقيمة للسمة animation-timeline.
  • يحدّد العنصر .scroller في الواقع "مخططًا زمنيًا للتمرير" بالاسم --tl. بشكلٍ تلقائي، لن يكون مرئيًا إلا للعناصر الفرعية، ولكن بما أنّ .parent ضبطته على أنّه scroll-timeline-root، سيتم ربطه به.
  • يستخدم العنصر .subject المخطط الزمني --tl. يتنقّل في شجرة العناصر الأصلية إلى أن يعثر على --tl في .parent. عندما يشير --tl في .parent إلى --tl في .scroller، سيتتبّع .subject بشكل أساسي المخطط الزمني لتقدّم التمرير في .scroller.

بعبارة أخرى، يمكنك استخدام timeline-root لنقل مخطط زمني إلى عنصر رئيسي (يُعرف أيضًا باسم رفع المستوى)، ليتمكّن جميع العناصر الفرعية من الوصول إليه.

يمكن استخدام السمة timeline-scope مع كلّ من "المخططات الزمنية للتمرير" و"المخططات الزمنية للعرض".

المزيد من العروض التوضيحية والمراجع

تتوفّر جميع العروض التوضيحية الواردة في هذه المقالة على الموقع الإلكتروني المصغّر scroll-driven-animations.style. يتضمّن الموقع الإلكتروني العديد من العروض التوضيحية الأخرى لتسليط الضوء على الإمكانات المتاحة باستخدام الرسوم المتحركة المستندة إلى التمرير.

أحد العروض التوضيحية الإضافية هو قائمة أغلفة الألبومات هذه. تدور كل صورة غلاف بشكل ثلاثي الأبعاد عندما تكون في وسط الشاشة.

العرض التوضيحي: Cover Flow

✨ جرِّب الميزة بنفسك

أو هذا العرض التوضيحي لترتيب البطاقات الذي يستفيد من position: sticky. عندما تتراكم البطاقات، يتم تصغير البطاقات العالقة، ما يؤدي إلى إنشاء تأثير عمق جميل. في النهاية، تنزلق الحزمة بأكملها خارج نطاق العرض كمجموعة.

العرض التوضيحي: ترتيب البطاقات.

✨ جرِّب الميزة بنفسك

تتضمّن scroll-driven-animations.style أيضًا مجموعة من الأدوات، مثل العرض المرئي لمدى تقدّم "المخطط الزمني للعرض" الذي تم تضمينه سابقًا في هذه المشاركة.

تم أيضًا تناول الحركات المستندة إلى التمرير في كل ما هو جديد في Web Animations في مؤتمر Google I/O لعام 2023.