1. قبل البدء
تسمح لك الصور المتحركة المستندة إلى الانتقالات بالتحكّم في تشغيل صورة متحركة استنادًا إلى موضع الانتقال في حاوية الانتقال. وهذا يعني أنّه عند التمرير للأعلى أو للأسفل، يتم تقديم أو ترجيع الصورة المتحركة. بالإضافة إلى ذلك، باستخدام الصور المتحرّكة المستندة إلى الانتقال، يمكنك أيضًا التحكّم في صورة متحرّكة استنادًا إلى موضع عنصر داخل حاوية الانتقال. يتيح لك ذلك إنشاء تأثيرات مثيرة للاهتمام، مثل صورة خلفية متغيّرة، وأشرطة تقدّم التمرير، والصور التي تظهر تدريجيًا.
يتيح لك الإصدار 115 من Chrome استخدام مجموعة من فئات JavaScript وخصائص CSS التي تتيح لك إنشاء صور متحركة بيانية بسهولة باستخدام ميزة الانتقال إلى الأسفل أو الأعلى. تعمل واجهات برمجة التطبيقات الجديدة هذه مع واجهات برمجة التطبيقات الحالية لـ Web Animations وCSS Animations.
يشرح لك هذا الدرس التطبيقي حول الترميز كيفية إنشاء صور متحركة يتم تشغيلها من خلال الانتقال إلى الأسفل أو للأعلى باستخدام CSS. من خلال إكمال هذا الدليل التعليمي حول الرموز البرمجية، ستتعرّف على العديد من خصائص CSS الجديدة التي توفّرها هذه الميزة المشوّقة، مثل scroll-timeline
وview-timeline
وanimation-timeline
وanimation-range
.
المُعطيات
- كيفية إنشاء تأثير مرئي للخلفية باستخدام مخطط زمني للانتقال في CSS
- كيفية إنشاء شريط تقدّم باستخدام مخطط زمني للانتقال في CSS
- كيفية إنشاء تأثير لكشف الصورة باستخدام "عرض المخطط الزمني" في CSS
- كيفية استهداف أنواع مختلفة من نطاقات "مخطط عرض الوقت" في CSS
المتطلبات
إحدى مجموعات الأجهزة التالية:
- إصدار حديث من Chrome (115 أو إصدار أحدث) على ChromeOS أو macOS أو Windows مع تفعيل علامة "ميزات منصة الويب التجريبية"
- فهم أساسي للغة HTML
- فهم أساسي للغة CSS، لا سيما الرسومات المتحركة في CSS
2. الإعداد
يتوفّر كل ما تحتاجه لهذا المشروع في مستودع GitHub. للبدء، يمكنك استنساخ الرمز البرمجي وفتحه في بيئة المطوّر المفضّلة لديك.
- افتح علامة تبويب جديدة في المتصفّح وانتقِل إلى https://github.com/googlechromelabs/io23-scroll-driven-animations-codelab.
- استنسِخ المستودع.
- افتح الرمز في بيئة تطوير البرامج المتكاملة (IDE) المفضّلة لديك.
- شغِّل
npm install
لتثبيت التبعيات. - شغِّل
npm start
وانتقِل إلى http://localhost:3000/. - بدلاً من ذلك، إذا لم يكن npm مثبّتًا، افتح ملف
src/index.html
في Chrome.
3- التعرّف على الجداول الزمنية للرسوم المتحرّكة
يتم تشغيل الرسم المتحرك المُرفَق بعنصر تلقائيًا في "المخطط الزمني للمستند". وهذا يعني أنّه عند تحميل الصفحة، يتقدّم التأثير المتحرك مع مرور الوقت. هذا هو المخطط الزمني التلقائي للحركة، وكان حتى الآن المخطط الزمني الوحيد للحركة الذي يمكنك الوصول إليه.
باستخدام الصور المتحركة المستندة إلى الانتقال للأعلى أو للأسفل، يمكنك الوصول إلى نوعَين جديدَين من المخططات الزمنية:
- الانتقال للأسفل أو للأعلى في مخطط التقدّم الزمني
- عرض المخطط الزمني للتقدّم
في CSS، يمكن إرفاق هذه المخططات الزمنية بحركة باستخدام السمة animation-timeline
. اطّلِع على معنى هذه المخططات الزمنية الجديدة واختلافاتها عن بعضها.
الانتقال للأسفل أو للأعلى في مخطط التقدّم الزمني
مخطط "تقدّم الانتقال للأسفل أو للأعلى" هو مخطط زمني للحركة المتحركة مرتبط بتقدّم موضع الانتقال للأسفل أو للأعلى في حاوية الانتقال للأسفل أو للأعلى، والتي تُعرف أيضًا باسم "نافذة الانتقال للأسفل أو للأعلى" أو "أداة الانتقال للأسفل أو للأعلى"، على طول محور معيّن. تحوّل هذه الدالة موضعًا في نطاق التمرير إلى نسبة مئوية من مستوى التقدّم على طول مخطط زمني.
يمثّل موضع الانتقال إلى أعلى الصفحة من البداية نسبة تقدّم% 0، ويمثّل موضع الانتقال إلى أعلى الصفحة من النهاية نسبة تقدّم% 100. في الرسم البياني التالي، يُرجى العِلم أنّه يتم احتساب مستوى التقدّم من 0% إلى 100% أثناء التمرير للأسفل في شريط التمرير.
عرض المخطط الزمني للتقدّم
يرتبط هذا النوع من المخطط الزمني بالتقدّم النسبي لعنصر معيّن ضمن حاوية لفائف. تمامًا مثل الجدول الزمني لتقدّم الانتقال للأعلى أو للأسفل، يتم تتبُّع إزاحة الانتقال للأعلى أو للأسفل. على عكس مخطط "تقدّم الانتقال إلى الأسفل أو الأعلى"، فإنّ التقدّم يعتمد على الموضع النسبي للموضوع ضمن شريط التمرير هذا. يشبه ذلك العنصر IntersectionObserver
الذي يتتبّع مقدار ظهور العنصر في شريط التمرير. إذا لم يكن العنصر مرئيًا في شريط التمرير، يعني ذلك أنّه لا يتقاطع. إذا كان مرئيًا داخل شريط التمرير، حتى لو كان الجزء الأصغر منه، يعني ذلك أنّه يتداخل.
يبدأ مخطط العرض الزمني للتقدّم من لحظة بدء تداخل الجسم مع شريط التمرير وينتهي عند توقّف الجسم عن التداخل مع شريط التمرير. في الرسم البياني التالي، يُرجى العِلم أنّ مستوى التقدّم يبدأ بالارتفاع من 0% عندما يدخل الجسم حاوية التمرير ويصل إلى 100% بحلول الوقت الذي يغادر فيه حاوية التمرير.
يتم تلقائيًا إرفاق صورة متحركة مرتبطة بمخطط "عرض مستوى التقدّم الزمني" بالنطاق الكامل له. يبدأ ذلك من لحظة دخول الهدف إلى نافذة التمرير وينتهي عند خروجه منها.
من الممكن أيضًا ربطه بجزء معيّن من مخطط "عرض مستوى التقدّم" من خلال تحديد النطاق الذي يجب إرفاقه به. على سبيل المثال، يمكن أن يحدث ذلك فقط عندما يدخل الهدف إلى شريط التمرير. في الرسم البياني التالي، يبدأ مستوى التقدّم بالارتفاع من 0% عندما يدخل الجسم إلى حاوية التمرير، ولكنه يصل إلى 100% من اللحظة التي يتداخل فيها بالكامل.
إنّ نطاقات "عرض المخطط الزمني" المحتملة التي يمكنك استهدافها هي cover
وcontain
وentry
وexit
وentry-crossing
وexit-crossing
. يتم شرح هذه النطاقات لاحقًا في هذا الدليل التعليمي حول رموز برمجية، ولكن إذا أردت معرفة ذلك الآن، يمكنك استخدام الأداة المتوفّرة على الرابط https://goo.gle/view-timeline-range-tool لمعرفة ما يمثّله كل نطاق.
4. إنشاء تأثير مرئي للخلفية
التأثير الأول الذي يجب إضافته إلى الصفحة هو تأثير التمويه في الخلفية على صورة الخلفية الرئيسية. أثناء الانتقال للأسفل في الصفحة، من المفترض أن تتحرك صورة الخلفية، ولكن بسرعة مختلفة. ولإجراء ذلك، يمكنك الاعتماد على مخطط زمني لتقدّم الانتقال للأعلى أو للأسفل.
لتنفيذ ذلك، عليك اتّباع خطوتَين:
- أنشئ صورة متحركة تغيّر موضع صورة الخلفية.
- اربط الصورة المتحركة بتقدم الانتقال في المستند.
إنشاء الصورة المتحركة
- لإنشاء التأثير المتحرك، استخدِم مجموعة عادية من اللقطات الرئيسية. في هذا الحقل، حرِّك موضع الخلفية من 0% عموديًا إلى 100%:
src/styles.css
@keyframes move-background {
from {
background-position: 50% 0%;
}
to {
background-position: 50% 100%;
}
}
- الآن، يمكنك إرفاق هذه الإطارات الرئيسية بعنصر الجسم:
src/styles.css
body {
animation: 1s linear move-background;
}
باستخدام هذا الرمز، تتم إضافة الحركة move-background
إلى عنصر النص الأساسي. تم ضبط سمة animation-duration
على ثانية واحدة، وهي تستخدم تسوية linear
.
ربط الصورة المتحركة بتقدّم الانتقال للأعلى أو للأسفل في العنصر الجذر باستخدام مخطط زمني مجهول لتقدّم الانتقال للأعلى أو للأسفل
إنّ أسهل طريقة لإنشاء مخطط زمني لتقدّم الانتقال إلى أعلى أو أسفل الصفحة هي استخدام الدالة scroll()
. يؤدي ذلك إلى إنشاء مخطط زمني مجهول لتقدّم الانتقال للأعلى أو للأسفل يمكنك ضبطه كقيمة لسمة animation-timeline
.
تقبل الدالة scroll()
وسيطتَي <scroller>
و<axis>
.
في ما يلي القيم المقبولة للوسيطة <scroller>
:
nearest
. يستخدم أقرب حاوية لانتقال الصفحة لأعلى أو للأسفل (الإعداد التلقائي).root
: يستخدم مساحة عرض المستند كسمة حاوية للانتقال.self
. يستخدم العنصر نفسه كسلة لفائف.
في ما يلي القيم المقبولة للوسيطة <axis>
:
block
: يستخدم مقياس التقدّم على طول محور الكتلة لحاوية التمرير (تلقائي).inline
. يستخدم مقياس التقدّم على طول المحور المضمّن لحاوية التمرير.y
. يستخدم مقياس التقدّم على طول محور ص لحاوية التمرير.x
. يستخدم مقياس التقدّم على طول محور x لحاوية التمرير.
لربط الصورة المتحركة بعنصر التمرير الرئيسي على محور الكتلة، تكون القيم التي يتم تمريرها إلى scroll()
هي root
وblock
. وتكون القيمة الإجمالية scroll(root block)
.
- اضبط
scroll(root block)
كقيمة لسمةanimation-timeline
في النصّ. - بالإضافة إلى ذلك، بما أنّ
animation-duration
بالثواني لا معنى له، اضبط المدة علىauto
. إذا لم تحدّد قيمةanimation-duration
، سيتم ضبطها تلقائيًا علىauto
.
src/styles.css
body {
animation: linear move-background;
animation-duration: auto;
animation-timeline: scroll(root block);
}
بما أنّ شريط التمرير الجذر هو أيضًا أقرب شريط تمرير رئيسي لعنصر الجسم، يمكنك أيضًا استخدام القيمة nearest
:
src/styles.css
body {
animation: linear move-background;
animation-duration: auto;
animation-timeline: scroll(nearest block);
}
وبما أنّ nearest
وblock
هما القيم التلقائية، يمكنك أيضًا اختيار حذفهما. في هذه الحالة، يمكن تبسيط الرمز إلى ما يلي:
src/styles.css
body {
animation: linear move-background;
animation-duration: auto;
animation-timeline: scroll();
}
التحقّق من التغييرات
إذا سارت الأمور على ما يرام، من المفترض أن يظهر لك ما يلي:
إذا لم يكن الأمر كذلك، يمكنك الاطّلاع على فرع solution-step-1
من الرمز.
5- إنشاء شريط تقدّم لمعرض الصور
تتضمّن الصفحة لوحة عرض دوّارة أفقية تحتاج إلى شريط تقدّم للإشارة إلى الصورة التي تطّلع عليها حاليًا.
يظهر تنسيق لوحة العرض الدوّارة على النحو التالي:
src/index.html
<div class="gallery">
<div class="gallery__scrollcontainer" style="--num-images: 3;">
<div class="gallery__progress"></div>
<div class="gallery__entry">
...
</div>
<div class="gallery__entry">
...
</div>
<div class="gallery__entry">
...
</div>
</div>
</div>
تمّت إضافة اللقطات الرئيسية لشريط التقدم وتبدو على النحو التالي:
src/styles.css
@keyframes adjust-progress {
from {
transform: scaleX(calc(1 / var(--num-images)));
}
to {
transform: scaleX(1);
}
}
يجب إرفاق هذه الصورة المتحركة بالملف .عنصر gallery__progress
يتضمّن مخططًا زمنيًا لتقدّم الانتقال للأسفل أو للأعلى كما هو موضّح في الخطوة السابقة، يمكنك تحقيق ذلك من خلال إنشاء مخطط زمني مجهول لتقدّم الانتقال باستخدام الدالة scroll()
:
src/styles.css
.gallery__progress {
animation: linear adjust-progress;
animation-duration: auto;
animation-timeline: scroll(nearest inline);
}
على الرغم من أنّه قد يبدو أنّ هذه القطعة من الرمز البرمجي ستعمل، إلا أنّها لا تعمل بسبب آلية عمل عمليات البحث التلقائية لحاويات التمرير باستخدام nearest
. عند البحث عن أقرب شريط تمرير، سيأخذ العنصر في الاعتبار فقط العناصر التي يمكن أن تؤثّر في موضعه. بما أنّ .gallery__progress
تم وضعه بشكل مطلق، فإنّ أول عنصر رئيسي سيحدّد موضعه هو عنصر .gallery
لأنّه تم تطبيق position: relative
عليه. وهذا يعني أنّ عنصر .gallery__scrollcontainer
، وهو شريط التمرير الذي يجب استهدافه، لا يتم أخذه بعين الاعتبار على الإطلاق أثناء عملية البحث التلقائية هذه.
لحلّ هذه المشكلة، أنشئ مخططًا زمنيًا مُعنوَنًا لتقدّم الانتقال في العنصر .gallery__scrollcontainer
واربط العنصر .gallery__progress
به باستخدام هذا الاسم.
أنشئ مخططًا زمنيًا مُسمّىً لتقدّم الانتقال للأعلى أو للأسفل واربطه.
لإنشاء مخطط زمني مُعنوَن لتقدّم الانتقال إلى أعلى أو أسفل الصفحة في عنصر معيّن، اضبط سمة scroll-timeline-name
CSS في حاوية الانتقال إلى أعلى أو أسفل الصفحة على قيمة تفضّلها. يجب أن تبدأ القيمة بـ --
.
وبما أنّ المعرض يتم التمرير فيه أفقيًا، عليك أيضًا ضبط السمة scroll-timeline-axis
. القيم المسموح بها هي نفسها وسيطة <axis>
في دالة scroll()
.
أخيرًا، لربط الصورة المتحركة بجدول زمني لتقدّم الانتقال، اضبط سمة animation-timeline
على العنصر الذي يجب أن تظهر عليه الصورة المتحركة على القيمة نفسها للمعرّف المستخدَم في scroll-timeline-name
.
- عدِّل ملف
styles.css
لتضمين ما يلي:
src/styles.css
.gallery__scrollcontainer {
/* Create the gallery-is-scrolling timeline */
scroll-timeline-name: --gallery-is-scrolling;
scroll-timeline-axis: inline;
}
.gallery__progress {
animation: linear adjust-progress;
animation-duration: auto;
/* Set gallery-is-scrolling as the timeline */
animation-timeline: --gallery-is-scrolling;
}
التحقّق من التغييرات
إذا سارت الأمور على ما يرام، من المفترض أن يظهر لك ما يلي:
إذا لم يكن الأمر كذلك، يمكنك الاطّلاع على فرع solution-step-2
من الرمز.
6- إضافة حركة إلى صور معرض الصور عند دخولها وخروجها من مساحة التمرير
عرض صور المعرض بشكل تدريجي
إعداد مخطط زمني مجهول لعرض مستوى التقدّم
يمكنك إضافة تأثير جميل على صور المعرض من خلال تمويهها أثناء ظهورها. ويمكنك استخدام "عرض المخطط الزمني للتقدّم" لهذا الغرض.
لإنشاء مخطط زمني لتقدّم عرض الإعلانات، يمكنك استخدام الدالة view()
. وسيطاتها المقبولة هي <axis>
و<view-timeline-inset>
.
- العنصر
<axis>
هو نفسه العنصر المستخدَم في مخطط "تقدّم الانتقال للأسفل أو للأعلى"، ويحدّد المحور الذي تريد تتبُّعه. - باستخدام
<view-timeline-inset>
، يمكنك تحديد قيمة متغيّرة (موجبة أو سالبة) لتعديل الحدود عندما يكون العنصر مرئيًا أو غير مرئي.
- تمّت إضافة اللقطات الرئيسية، لذا ما عليك سوى إرفاقها. لإجراء ذلك، أنشئ مخططًا زمنيًا لعرض مستوى التقدّم في كل عنصر
.gallery__entry
.
src/styles.css
@keyframes animate-in {
from {
opacity: 0;
clip-path: inset(50% 0% 50% 0%);
}
to {
opacity: 1;
clip-path: inset(0% 0% 0% 0%);
}
}
.gallery__entry {
animation: linear animate-in;
animation-duration: auto;
animation-timeline: view(inline);
}
الحد من نطاق "مخطط زمني لتقدّم عرض"
في حال حفظ ملف CSS وتحميل الصفحة، ستلاحظ تلاشي العناصر، ولكن يبدو أنّ هناك مشكلة. تبدأ العناصر من مستوى الشفافية 0
عندما تكون خارج نطاق العرض تمامًا ولا تنتهي إلا عند مستوى الشفافية 1
عندما تخرج تمامًا.
ويعود السبب في ذلك إلى أنّ النطاق التلقائي لمخطط "التقدّم في عرض الإعلانات" هو النطاق الكامل. ويُعرف هذا النطاق باسم cover
.
- لاستهداف نطاق
entry
فقط من الهدف، استخدِم سمةanimation-range
في CSS لتحديد وقت تشغيل الحركة.
src/styles.css
.gallery__entry {
animation: linear fade-in;
animation-duration: auto;
animation-timeline: view(inline);
animation-range: entry 0% entry 100%;
}
يتم تشغيل الرسم المتحرك الآن من entry 0%
(الموضوع على وشك الدخول إلى شريط التمرير) إلى entry 100%
(الموضوع قد دخل بالكامل إلى شريط التمرير).
في ما يلي نطاقات عرض المخطط الزمني المحتمَلة:
cover
: يمثّل النطاق الكامل للمخطط الزمني لتقدّم العرض.entry
: يمثّل النطاق الذي يدخل فيه المربّع الرئيسي نطاق ظهور مستوى تقدّم العرض.exit
: يمثّل النطاق الذي يخرج فيه المربّع الرئيسي من نطاق ظهور مستوى تقدّم العرض.entry-crossing
: يمثّل النطاق الذي يقطع فيه المربّع الرئيسي حافة الحدّ النهائي.exit-crossing
: يمثّل النطاق الذي يقطع فيه المربّع الرئيسي حافة حدود البداية.contain
: يمثّل النطاق الذي يكون فيه المربّع الرئيسي مضمّنًا بالكامل في نطاق ظهور مستوى التقدّم في العرض أو يغطّيه بالكامل ضمن مساحة التمرير. يعتمد ذلك على ما إذا كان الهدف أطول أو أقصر من شريط التمرير.
استخدِم الأداة المتوفّرة على الرابط https://goo.gle/view-timeline-range-tool لمعرفة ما يمثّله كل نطاق ومدى تأثير النسب المئوية في موضعَي البداية والنهاية.
- بما أنّ نطاقَي البدء والانتهاء متطابقان هنا ويتم استخدام العناصر المرجعية التلقائية، يمكنك تبسيط
animation-range
إلى اسم نطاق حركة متحرّكة واحد:
src/styles.css
.gallery__entry {
animation: linear animate-in;
animation-duration: auto;
animation-timeline: view(inline);
animation-range: entry;
}
تمويه صور المعرض
- لإخفاء الصور عند خروجها من شريط التمرير، يمكنك إجراء ما هو مشابه لما يتم تنفيذه في التأثير المتحرك "الظهور"، ولكن مع استهداف نطاق مختلف.
src/styles.css
@keyframes animate-out {
from {
opacity: 1;
clip-path: inset(0% 0% 0% 0%);
}
to {
opacity: 0;
clip-path: inset(50% 0% 50% 0%);
}
}
.gallery__entry {
animation: linear animate-in, linear animate-out;
animation-duration: auto;
animation-timeline: view(inline);
animation-range: entry, exit;
}
سيتم تطبيق الإطارات الرئيسية animate-in
على النطاق entry
والإطارات الرئيسية animate-out
على النطاق exit
.
التحقّق من التغييرات
إذا سارت الأمور على ما يرام، من المفترض أن يظهر لك ما يلي:
إذا لم يكن الأمر كذلك، يمكنك الاطّلاع على فرع solution-step-3
من الرمز.
7- أضِف حركة إلى صور المعرض عند دخولها وخروجها من مساحة التمرير، وذلك باستخدام مجموعة واحدة من الإطارات الرئيسية.
حالة مجموعة واحدة من اللقطات الرئيسية
بدلاً من إرفاق متحركَين بنطاقات مختلفة، من الممكن إنشاء مجموعة واحدة من اللقطات الرئيسية التي تحتوي على معلومات النطاق.
يظهر شكل الإطارات الرئيسية على النحو التالي:
@keyframes keyframes-name {
range-name range-offset {
...
}
range-name range-offset {
...
}
}
- اجمع الإطارات الرئيسية لمؤثر التمويه بالظهور والتمويه بالاختفاء على النحو التالي:
src/styles.css
@keyframes animate-in-and-out {
entry 0% {
opacity: 0;
clip-path: inset(50% 0% 50% 0%);
}
entry 90% {
opacity: 1;
clip-path: inset(0% 0% 0% 0%);
}
exit 10% {
opacity: 1;
clip-path: inset(0% 0% 0% 0%);
}
exit 100% {
opacity: 0;
clip-path: inset(50% 0% 50% 0%);
}
}
- عندما تكون معلومات النطاق متوفّرة في اللقطات الرئيسية، لن تحتاج إلى تحديد
animation-range
بشكل منفصل بعد الآن. اربط الإطارات الرئيسية كسمةanimation
.
src/styles.css
.gallery__entry {
animation: linear animate-in-and-out both;
animation-duration: auto;
animation-timeline: view(inline);
}
التحقّق من التغييرات
إذا سارت الأمور على ما يرام، من المفترض أن تظهر لك النتيجة نفسها التي حصلت عليها في الخطوة السابقة. إذا لم يكن الأمر كذلك، يمكنك الاطّلاع على فرع solution-step-4
من الرمز.
8. تهانينا!
لقد أكملْت هذا الدرس التطبيقي حول الترميز وأصبحت الآن تعرف كيفية إنشاء مخططات زمنية لتقدّم الانتقال إلى الأسفل وعرض مخططات زمنية لتقدّم الانتقال إلى الأعلى في CSS.
مزيد من المعلومات
المصادر: