اذهب إلى المحتوى

البحث في الموقع

المحتوى عن 'animation'.

  • ابحث بالكلمات المفتاحية

    أضف وسومًا وافصل بينها بفواصل ","
  • ابحث باسم الكاتب

نوع المحتوى


التصنيفات

  • الإدارة والقيادة
  • التخطيط وسير العمل
  • التمويل
  • فريق العمل
  • دراسة حالات
  • التعامل مع العملاء
  • التعهيد الخارجي
  • السلوك التنظيمي في المؤسسات
  • عالم الأعمال
  • التجارة والتجارة الإلكترونية
  • نصائح وإرشادات
  • مقالات ريادة أعمال عامة

التصنيفات

  • مقالات برمجة عامة
  • مقالات برمجة متقدمة
  • PHP
    • Laravel
    • ووردبريس
  • جافاسكربت
    • لغة TypeScript
    • Node.js
    • React
    • Vue.js
    • Angular
    • jQuery
    • Cordova
  • HTML
  • CSS
    • Sass
    • إطار عمل Bootstrap
  • SQL
  • لغة C#‎
    • ‎.NET
    • منصة Xamarin
  • لغة C++‎
  • لغة C
  • بايثون
    • Flask
    • Django
  • لغة روبي
    • إطار العمل Ruby on Rails
  • لغة Go
  • لغة جافا
  • لغة Kotlin
  • لغة Rust
  • برمجة أندرويد
  • لغة R
  • الذكاء الاصطناعي
  • صناعة الألعاب
  • سير العمل
    • Git
  • الأنظمة والأنظمة المدمجة

التصنيفات

  • تصميم تجربة المستخدم UX
  • تصميم واجهة المستخدم UI
  • الرسوميات
    • إنكسكيب
    • أدوبي إليستريتور
  • التصميم الجرافيكي
    • أدوبي فوتوشوب
    • أدوبي إن ديزاين
    • جيمب GIMP
    • كريتا Krita
  • التصميم ثلاثي الأبعاد
    • 3Ds Max
    • Blender
  • نصائح وإرشادات
  • مقالات تصميم عامة

التصنيفات

  • مقالات DevOps عامة
  • خوادم
    • الويب HTTP
    • البريد الإلكتروني
    • قواعد البيانات
    • DNS
    • Samba
  • الحوسبة السحابية
    • Docker
  • إدارة الإعدادات والنشر
    • Chef
    • Puppet
    • Ansible
  • لينكس
    • ريدهات (Red Hat)
  • خواديم ويندوز
  • FreeBSD
  • حماية
    • الجدران النارية
    • VPN
    • SSH
  • شبكات
    • سيسكو (Cisco)

التصنيفات

  • التسويق بالأداء
    • أدوات تحليل الزوار
  • تهيئة محركات البحث SEO
  • الشبكات الاجتماعية
  • التسويق بالبريد الالكتروني
  • التسويق الضمني
  • استسراع النمو
  • المبيعات
  • تجارب ونصائح
  • مبادئ علم التسويق

التصنيفات

  • مقالات عمل حر عامة
  • إدارة مالية
  • الإنتاجية
  • تجارب
  • مشاريع جانبية
  • التعامل مع العملاء
  • الحفاظ على الصحة
  • التسويق الذاتي
  • العمل الحر المهني
    • العمل بالترجمة
    • العمل كمساعد افتراضي
    • العمل بكتابة المحتوى

التصنيفات

  • الإنتاجية وسير العمل
    • مايكروسوفت أوفيس
    • ليبر أوفيس
    • جوجل درايف
    • شيربوينت
    • Evernote
    • Trello
  • تطبيقات الويب
    • ووردبريس
    • ماجنتو
    • بريستاشوب
    • أوبن كارت
    • دروبال
  • الترجمة بمساعدة الحاسوب
    • omegaT
    • memoQ
    • Trados
    • Memsource
  • برامج تخطيط موارد المؤسسات ERP
    • تطبيقات أودو odoo
  • أنظمة تشغيل الحواسيب والهواتف
    • ويندوز
    • لينكس
  • مقالات عامة

التصنيفات

  • آخر التحديثات

أسئلة وأجوبة

  • الأقسام
    • أسئلة البرمجة
    • أسئلة ريادة الأعمال
    • أسئلة العمل الحر
    • أسئلة التسويق والمبيعات
    • أسئلة التصميم
    • أسئلة DevOps
    • أسئلة البرامج والتطبيقات

التصنيفات

  • كتب ريادة الأعمال
  • كتب العمل الحر
  • كتب تسويق ومبيعات
  • كتب برمجة
  • كتب تصميم
  • كتب DevOps

ابحث في

ابحث عن


تاريخ الإنشاء

  • بداية

    نهاية


آخر تحديث

  • بداية

    نهاية


رشح النتائج حسب

تاريخ الانضمام

  • بداية

    نهاية


المجموعة


النبذة الشخصية

تم العثور على 16 نتائج

  1. إنّ هدف الوحدات عمومًا هو توزيع المهام عن طريق تعريف توابع الواجهة البرمجية (API) والحدّ من رؤية السلوك (أجسام التوابع) والبيانات (العناصر والمتغيّرات). معظم المنصّات البرمجيّة تتضمّن دعمًا داخليًّا للوحدات، حتّى أصبح استخدامها أمرًا مسلّمًا به. ولكنّ JavaScript المستخدمة من طرف العميل لا تستخدم الوحدات حاليًّا، وتؤدي إلى احتدام النقاشات المليئة بين مؤيّد ومعارض للحلّ المشهور (الإضافات add-ons) مثل CommonJS و تعريف الوحدة غير المتزامن (AMD). أبقِ في ذهنك عندما تقوم بمقارنة الحلول المطروحة، أنّ نظام الوحدات في Angular لا يقوم بتحميل الوحدة. فهو لا يقوم بتحميل الشيفرة المصدرية من ملفّاتٍ أو من الإنترنت. فالحلّ الذي تقدّمه Angular هو نظام الوحدات المدمج فيها، والذي يرتبط ارتباطًا وثيقًا بنظام حقن التابعية المدمج أيضًا في Angular. معًا، يكوّن هذان النّظامان جزءًا كبيرًا من البنية التّحتيّة لـAngular. ولكن هل نحن بحاجةٍ إليها حقًّا؟ صحيحٌ أنّ بإمكان أيّ مطوّر تعلّمها، ولكن لمَ نحتاجها؟ تُشكّل الوحدات وحقن التّابعيّة كلّ بنية Angular، ولكن كما رأينا فإنّ Angular تسمح لنا بالبدء دون استخدام نظام الوحدات. حتّى الآن، كان بإمكاننا إنجاز الكثير ببساطة عن طريق تعريف المتحكمات كتوابع معرّفة في المجال العامّ. ولكنّ ذلك لم يكن ليعمل لولا القليل من الإعدادات، وهذه الإعدادات سمحت للتّوجيه ng-controller بالبحث عن توابع التّحكّم في المجال العام وأيضًا في نظام الوحدات. هذه الطريقة السهلة في استخدام المجال العام مسموحةٌ في Angular، ولكن فقط إلى هذه النقطة. لماذا نستخدم وحدات Angular؟ لابدّ لك من فهم وإتقان نظام الوحدات في Angular لتتمكّن من تجاوز الأساسيّات فيها والغوص في المفاهيم العميقة. لا تسعى هذه السلسلة لإقناعك بالأهمّيّة الكامنة في الوحدات وفي حقن التّابعيّة في Angular، فعندما تواجهك مشكلة إدارة التّعقيد في تطبيقك فالأمر يعود إلى تجربتك الشّخصيّة في أفضل الممارسات البرمجيّة، والحلّ الأبسط سيكون الأفضل. سيغطّي هذا الكتاب الوحدات في Angular ومبدأ حقن التّابعيّة بما يشمل الجزء الأهمّ منها في Angular. لنبدأ بنظرةٍ عامّة إلى المزايا الهامّة التي تدفعنا لاستخدام نظام الوحدات: مكوّنات مخصّصة - لتعريف المتحكّمات الخاص بك، التّوجيهات، المرشّحات، والمؤثّرات الخاصّة، لا بدّ من استخدام نظام الوحدات.(يمكننا استثناء المتحكّمات كما أشرنا سابقًا.) حقن التّابعيّة - الخدمات ليست إلّا كائنات وتوابع JavaScript عاديّة، إلّا أنّ الخدمات التي يتمّ إنشاؤها في نظام الوحدات يمكن أن تُحقن بسهولة مع التّبعيّات الخاصّة بها، وذلك إن كانت تتيح حقن التّابعيّة فيها. الوحدات الخارجيّة - هناك نظامٌ بيئيّ مثيرٌ للاهتمام، مجّانيٌّ ومفتوح المصدر من الإضافات لـAngular، وقد قام بكتابة بعض هذه الإضافات فريق تطوير قلب Angular وكذلك المطوّرون كطرفٍ ثالث. لاستخدام أيٍّ من هذه المكاتب في تطبيقك لا بُدّ من استخدام نظام الوحدات. إعدادات وقت-التّحميل - يسمح نظام الوحدات في Angular بالوصول إلى تعلّقات دورة الحياة (lifecycle hooks) المتعلّقة بالإعدادات الدّاخليّة لـAngular، وكذلك المتعلّقة بإعدادات الوحدات المضافة، وسنتطرّق لها في نهاية الفصل الأخير، حيث سنقوم بإعداد رأس HTML مخصص. الاختبار - إنّ البنية التّحتيّة الخاصّة بالاختبار في Angular تبيّن فاعليّة نظام حقن التّابعيّة والّذي يعتمد بدوره على نظام الوحدات. سيبيّن فصلٌ لاحقٌ، فصل الخدمات، كيف نقوم بتعريف مقدم لمكوّنات JavaScript المخصّصة. سنرى في هذا الفصل كيف نعرّف متحكّمًا، وسنقوم أيضًا بتحميل وحدةٍ خارجيّةٍ، وأثناء تنفيذ ذلك سنتعلّم أساسيّات نظام الوحدات في Angular. إنشاء وحدة التطبيق يمكن تهيئة تطبيق Angular باستخدام وحدةٍ جذريّة واحدة فقط. سنقوم بتسمية الوحدة في أمثلة هذا الفصل بالاسم app ويمكنك اختيار أيّ اسمٍ آخر إن أردت، إلّا أنّ هذا الاسم شائع الاستخدام في مرجع Angular. angular.module('app', []); أرجو أن تركّز على الوسيط الثاني للتابع module في مثالنا السابق، ورغم أنّه يبدو فارغًا، وله مظهر مصفوفة بريئة خالية ([]) إلّا أنّ وجود هذا الوسيط الثاني شديد الأهمّيّة، فبدونه سيتغيّر سلوك التّابع angular.module كليا، وسأشرح لك سلوك هذا التابع كما يلي: عند استدعاء التابع angular.module مع وجود الوسيط الثاني، سيعمل التّابع في نمط الإنشاء (create)، وسيقوم بإنشاء وحدةٍ ويسمّيها app إن لم يكن هناك وحدة بنفس الاسم سابقًا، أمّا عند استدعائه دون الوسيط الثّاني فسيعمل في نمط البحث (lookup)، فإن عثر على وحدةٍ بالاسم المعطى سيقوم بإعادتها، أمّا إن لم يجدها فسيقوم برمي خطأٍ يطلب تمرير الوسيط الثاني. قمنا في المثال السابق بالاستخدام الصحيح للتابع، ولكن كن حذرًا دومًا من الفرق بين الطريقتين في استدعاء هذا التّابع, أمّا بالنّسبة لهذه المصفوفة التي تمرر كوسيط، فهي تُستخدم لجلب الوحدات الخارجية التي سنناقشها في هذا الفصل، باستخدام وحدة animation في أمثلتنا. تحميل وحدة التطبيق في مستند HTML الذي يستضيف التّطبيق، يمكننا أن نأمر Angular بتحميل وحدة هذا التّطبيق عن طريق تمرير اسمه إلى التّوجيه ng-app. <body ng-app="app"> <!-- الأمثلة توضع هنا --> </body> ستكون جميع المكوّنات التي نضيفها إلى وحدة التّطبيق متاحةً للاستخدام. لنرى الآن كيف نقوم بتعريف متحكّم داخل وحدةً بدلًا من تعريفه في المجال العام. تعريف متحكم تتضمّن الواجهة البرمجية للعنصر module توابع لتعريف مكوّنات Angular المخصّصة. والمكوّن الوحيد الذي تعرفنا عليه سابقًا هو المتحكّم، لذا لنقم باستخدام التابع controller لإنشاء متحكّم. سنحتاج أوّلًا إلى جلب مرجعٍ لوحدة التّطبيق، وكما ذكرنا سابقًا، يجب أن نقوم باستدعاء التابع angular.module بدون تمرير الوسيط الثاني، وذلك كي يعمل في نمط البحث lookup. var app = angular.module('app'); app.controller('MessageController', function($scope) { $scope.message = "This is a model."; }); والآن، في مكان ما ضمن العنصر الذي قمنا فيه باستدعاء الوحدة عن طريق "ng-app="app، يمكننا استخدام التّوجيه ng-controller لتحميل المتحكّم. <p ng-controller="MessageController"> {{message}} </p> الناتج This is a model. وكما يمكنك أن ترى، فتعريف المتحكّم داخل الوحدة يحتاج إلى عمل أكثر بقليل من تعريفه في المجال العام، ولكنّه ليس بهذه الصعوبة أبدًا. سلسلة التعريفات لنفترض بأننا نريد تعريف متحكّمين للقالب التالي. <p ng-controller="MessageController"> {{message}} </p> <p ng-controller="AnotherMessageController"> {{message}} </p> إنّ توابع التعريف ضمن العنصر Module قابلةٌ للسَّلسَلة، حيث يمكننا إنشاء متحكّمين باستخدام عبارةٍ واحدة. angular.module('app') .controller('MessageController', function($scope) { $scope.message = "This is a model."; }) .controller('AnotherMessageController', function($scope) { $scope.message = "This is another model."; }); الناتج This is a model. This is another model. لاحظ أن الاستدعاء الأول للتابع controller لم تتبعه فاصلةٌ منقوطة. إن لم تعجبك هذه الطريقة في سَلسَلة الاستدعاءات، يمكنك استدعاء التابع module كلّما أردت الحصول على مرجعٍ للوحدة، أو يمكنك تخزين هذا المرجع في متغيّر، كما يبيّن المثال التالي. عند استخدامك لمتغيّر، سيكون من الجيّد أن تضعه ضمن تابعٍ يُستدعى آنيًّا (IIFE) أو أيّ مجالٍ مغلقٍ آخر، لمنع ذلك المتغيّر من أن يُنشأ في المجال العام. var app = angular.module('app'); app.controller('MessageController', function($scope) { $scope.message = "This is a model."; }); app.controller('AnotherMessageController', function($scope) { $scope.message = "This is another model."; }); يمكنك اختيار أيٍّ من الطريقتين، ولكنّ طريقة السَّلسلة هي الأكثر شيوعًا. تحميل الوحدات يُعدّ التحريك (animations) ميزةً جديدةً في Angular تمّت إضافتها إلى حزمة منفصلة اسمها ngAnimate. الخطوة الأولى لاستخدام التحريك هي تضمين ملف JavaScript المحتوي على الوحدة. الشيفرة المصدريّة للوحدة جزءٌ من قلب Angular، ولكنّها موجودةٌ في ملفٍّ منفصل، كما نرى أدناه. <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular.js"></script> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular-animate.js"></script> حان الوقت لنستخدم الوسيط الثّاني للتابع module كما يجب، فبدلًا من تمرير مصفوفةٍ خاليةٍ فيه سنقوم الآن بالتصريح عن الوحدات المتعلّقة بوحدتنا. angular.module('app', ['ngAnimate']); لقد قمنا الآن بتحميل ngAnimate إلى داخل وحدة التّطبيق، والآن ستقوم التّوجيهات ng-show و ng-hide و ng-class و العديد من التّوجيهات الأخرى بالتّحقّق من التحريك الخاصّ بـCSS وJavaScript أيضًا الذي يمكن تطبيقه على أحداث المستند مثل add و enter و leave و move و remove، وتطبيق هذا التّحريك شفّاف فهو لا يتطلّب أيّ تغيير على شيفرة القالب المكتوبة، وإن لم نكن قد طبّقنا هذا التّحريك سواء على شكل CSS أو كـJavaScript عن طريق تسجيل الحركة عبر module.animation، فإنّ الشيفرة ستسلك السّلوك الافتراضيّ لها بشكل طبيعيّ. <input type="checkbox" ng-model="showMessage"> Check the box to show the message <h2 ng-show="showMessage"> The secret message. </h2> بالنّقر على الـcheckbox ستقوم ng-show بعملها كالمعتاد، وسيتمّ التّبديل بين إظهار وإخفاء العنصر بشكلٍ فوريّ دون تدرّج أو تأثير اختفاءٍ بسيط، إلى أن نكتب شيفرة التّحريك في CSS أو JavaScript. في المثال التّالي سنستخدم CSS، وهي عمومًا الخيار الأفضل للتحريك بسبب الأسلوب التصريحي في كتابتها. يمكنك على أيّ حالٍ استخدام التابع animate في jQuery ليقوم بالمهمّة إن وجدت ذلك أسهل، أما Angular فتقوم بذلك عن طريق الوحدة module.animation. يتطلّب التّحكّم بتأثير الاختفاء التّدريجيّ استخدام أربع فئات CSS تقوم بالتّعلّق (hook)، وذلك حسب توثيق الواجهة البرمجية الخاصّ بالتّوجيه ng-show. هذه الفئات الأربعة هي ng-hide-add و ng-hide-add-active و ng-hide-remove و ng-hide-remove-active. .ng-hide-add, .ng-hide-remove { transition: all linear 1s; display: block !important; } .ng-hide-add.ng-hide-add-active, .ng-hide-remove { opacity: 0; } .ng-hide-add, .ng-hide-remove.ng-hide-remove-active { opacity: 1; } قد تحتاج إلى إضافة خصائص محدّدة من قبل المصنّع لبعض المتصفّحات حسب زوّار موقعك، مثل webkit-transition- الخاص بمتصفّح سفاري 6 لأنظمة iOS. (يُعدّ موقع caniuse.com مرجعًا جيّدًا لتوافق المتصفّحات مع HTML5 و CSS3.) أرجو أن تنتبه أيضًا إلى أنّ هذا التّحريك سيتمّ تطبيقه في كلّ الأماكن التي ستستخدم فيها ng-show و ng-hide في تطبيقك. يمكنك إضافة فئة CSS مخصّصة لتزيد قدرتك على التّحكّم، وذلك للعنصر ولمحدّد CSS الذي تتعامل معه، مثلًا يمكنك كتابة my-class.ng-hide-add. و my-class.ng-hide-remove. وهكذا. خاتمة أتمنى أن تكون سهولة إضافة ngAnimate قد أقنعتك بأهمّية فهم نظام الوحدات في Angular. ومن المفرح أن تعلم بأنّ ngAnimate ليست إلّا البداية ضمن الكثير من الوحدات المُضافة إلى Angular. يمكنك أن تختار وحداتٍ أخرى متاحةّ بشكلٍ مجّانيّ من هذا النّظام البيئيّ سريع النموّ الذي يعتمد على إبداعات المطوّرين من مواقع مثل GitHub، وذلك إضافةً إلى الوحدات التي تتيحها Angular أصلًا مثل ngResource وngRoute. أحد أكثر المشاريع شُهرةً هو AngularUI، الذي يحوي وحداتٍ عظيمة الأهمّيّة مثل UI Router وUI Bootstrap، ومعظم هذه الوحدات يمكن تحميله بسهولة في مشروعك باستخدام Bower، مدير حزم الويب، ولربّما ستبدأ بنشر وحدات Angular الخاصّة بك مفتوحة المصدر على GitHub وBower عندما تملك زمام Angular، وهذا ما أتمنّاه. تقدّم الوحدة ngAnimate إثباتًا واضحًا للقوّة المتاحة في الوحدات المضافة، ولكنّها لا تتضمّن استخدام البنية التّحتيّة لحقن التّابعيّة في Angular بسبب أسلوبها الجزئيّ في التكامل. سنغطّي حقن التّابعيّة في الفصل القادم، وذلك لأنّه يعمل يدًا بيد مع الوحدات. ترجمة وبتصرّف للفصل السادس من كتاب: Angular Basics لصاحبه: Chris Smith.
  2. هذا الدرس الرابع من سلسلة نصائح وحيل فوتوشوب، التي سنتعلم من خلالها العديد من الحيل والأدوات عند التصميم ببرنامج فوتوشوب بالإضافة إلى مجموعة من النصائح حول الإستخدام الأمثل للبرنامج. سنقوم في هذا الدرس بتصميم قلم وتحريكه لكتابة كلمة وسنراه يقوم بذلك بالحركة فعليًّا باستخدام برنامج فوتوشوب. وستكون النتيجة كالتالي: افتح ملفا جديدا في فوتوشوب ثم لوّن الخلفية كما تريد ثم استخدم أداة النص لكتابة أي كلمة أو عبارة تريدها مثلا: "حسوب". حوّل طبقة النص إلى طبقة صورة نقطية عبر النقر بالزر الأيمن على الطبقة واختيار Rasterize Type من القائمة. حدد هذه الطبقة واضغط Ctrl+J لصنع نسخة جديدة عنها ثم أخفِ الطبقة القديمة واستخدم أداة الممحاة لمسح جزء صغير من آخر النص. مجددًا حدّد الطبقة الجديدة ثم اضغط Ctrl+J ثم أخفِ الطبقة القديمة وامسح جزءًا إضافيًّا من النص ثم كرّر العملية حتى تمسح النص بالكامل. استخدم أدوات الأشكال واختر شكل القلم من بين الأشكال القياسية الموجودة في برنامج فوتوشوب أصلًا. ارسم شكل القلم ولوّنه كما تشاء (يمكنك استخدام صورة قلم حقيقي ببساطة). الآن اذهب إلى نافذة Window ثم فعّل نافذة Timeline ثم ابدأ بإضافة إطار Frame جديد وفي كل مرّة أظهِر طبقة جديدة من الطبقات النصيّة التي أخفيناها سابقًا مع تحريك القلم ووضع رأس القلم عند النقطة الأخيرة الظاهرة من النص وكرّر العملية حتى تصل إلى إظهار النص كاملًا. احفظ الملف من القائمة: File > Save for Web ثم اختر نوعية الملف GIF واحفظ الملف وستحصل على النتيجة التالية. طبعًا هذه نصيحة بسيطة ومختصرة ويمكنك تعديل العمل بخلفية مختلفة ونص آخر وقلم واقعي والتلاعب بعدد الإطارات ومدة إظهارها ...الخ
  3. لنستخدم CSS لرسم شخصية بيماكس (Baymax) من فيلم Big Hero 6. سنحرّك في هذا المنشور صورة خلفية، بالإضافة إلى تأثير حركة بتوقيت دقيق، ونقوم بإجراء عرض تجريبي CSS من عنصر HTML واحد. تجربة حية. عنصر واحد سنكون قادرين باستخدام العنصر الزائف على إنشاء أجزاء الوجه بعنصر HTML واحد. <div class="baymax"></div> التصميم لضبط المرحلة سنضيف تدرّجًا دقيقًا للشاشة لجعلها تبدو كرأس أبيض منحنٍ. سنستخدم لهذا تدرجًا شعاعيًا على عنصر body. body { background: radial-gradient(circle at center, #fff, #fff 50%, #aaa); background-size: 100% 100%; background-repeat: no-repeat; height: 100vh; } بعد ذلك نضع الوجه في مركز الصفحة. الفم خط أسود بسيط، وسنقوم بذلك باستخدام الخاصية border. .baymax { border-bottom: 1.5em solid #000; position: absolute; top: 50%; left: 50%; width: 50%; transform: translate(-50%, -40%); } تقوم الخاصية الأولى بتعيين إطار سفلي أسود بعرض 1.5em. ثمَّ يتموضع الخط باستخدام الموضع المطلق، فيندفع إلى الأسفل 50% ويتحرك من اليسار 50%. قيم الـ 50% هي بالنسبة إلى حجم العنصر الحاوي (body). المشكلة التي نواجهها الآن هي أنَّ العنصر يبدأ من منتصف طول وعرض الشاشة. إنَّه خارج المركز. لموازنة ذلك، نستخدم تحويلًا لسحب العنصر 50% يسارًا من عرضه، وإلى الأعلى 40% من عرضه. عند هذه المرحلة يصبح الفم في المركز على هذا النحو: إضافة العينين سنستخدم العناصر الزائفة before وafter لإضافة العينين إلى الوجه. لن يحتاج هذا إلى أي عنصر HTML إضافي وتتم معالجته بالكامل باستخدام CSS. .baymax::before { background: #000; border-radius: 50%; content: ""; position: absolute; width: 12em; height: 12em; left: -9em; top: -6em; transform: skewX(-4deg); } .baymax::after { background: #000; border-radius: 50%; content: ""; position: absolute; width: 12em; height: 12em; right: -9em; top: -6em; transform: skewX(4deg); } كل من هذه العناصر الزائفة لها خلفية سوداء، وحواف دائرية -border-radius: 50%; لجعلها دائرية. كلّ منها متموضع في نهاية الفم، وأخيرًا لها تحوّل skew لجعلها تبدو كأنَّها مائلة قليلًا للخلف. ستظهر النتيجة كما يلي: البطارية منخفضة هناك مشهدٌ مضحك في الفيلم حيث تنخفض بطارية بيماكس. فيترنَّح وتتدلَّى جفونه. يمكننا استخدام مزيج من الحركات والتدرّجات في الخلفية لإحداث التأثير. نريد أولًا أن نعطي الخلفية لونين. أسود لجزء العين المفتوح، وأبيض للجفن. يحتاج الجزء الأبيض أن يتموضع خارج العينين في البداية، ثمَّ سنحركه لجعل الجفون تتدلَّى. .baymax::before { background: linear-gradient(to bottom, #efefef, #efefef 50%, #000 50%, #000); background-position: 0 -100%; background-size: 200% 200%; ... } .baymax::after { background: linear-gradient(to bottom, #efefef, #efefef 50%, #000 50%, #000); background-position: 0 -100%; background-size: 200% 200%; ... } نحن الآن نضيف تدرّجًا خطيًّا في الخلفية، فنجعله ضعف ارتفاع الحاوية، ثم نحدد موضعه لذا يصبح النصف العلوي خارج الحاوية. مع وجود تدرّجات للخلفية في مكانين، يمكننا أن نضيف حركة keyframes للتحكم في حركة الجفون. @keyframes blink { 0%, 50% { background-position: 0 100%; } 85%, 95% { background-position: 0 75%; } 100% { background-position: 0 100%; } } قاعدة keyframes في الحركات هي طريقة لوصف سلسلة من الإطارات، باستخدام النسبة المئوية. تعود النسبة المئوية لمدى استمرار الحركة، لذا فإنَّ النسبة المئوية 50% منتصف الطريق عبر الحركة. بهذه الطريقة يمكننا ضبط الخلفية للبقاء مستيقظين حتى منتصف الحركة، ثمَّ بين الإطار 50% والإطار85%، تتحرك للأسفل، وثمَّ تستقر في نهاية الحركة. الخطوة التالية هي إخبار العناصر الزائفة أن تستخدم إطارات الحركة هذه. أضف خاصية animation للأنماط الحالية. .baymax::before { animation: blink 6s infinite; ... } .baymax::after { animation: blink 6s 0.1s infinite; ... } أخبرنا المتصفح هنا أن يستخدم حركة blink على كل عنصر. وضبطنا مدة الحركة إلى 6 ثواني وستستمر بشكلٍ لا نهائي. خاصية واحدة إضافية في المثال الثاني: تخبر المدة 0.1s بعد 6s المتصفح أن تتأخر الحركة لـ0.1 ثانية. يخلق هذا تأثير إغلاق العين الثانية بتأخيرٍ عن الأولى. وذلك يضيف التأثير المتدلي والمتعب ويجعلها تبدو أكثر واقعيةً. يجب أن تظهر النتيجة النهائية كما في الصورة: يمكنك مشاهدة تجربة حية. المتصفحات حذفت في أمثلة الشفرة أيّ بادئات معتادة webkit- وmoz-. لكن خاصيّات transform وanimation يجب أن تكون مسبوقة، وأنصحك باستخدام شيء ما مثل Autoprefixer لهذا. نسخة gif قابلة للمشاركة إليك نسخة gif متحركة يمكنك مشاركتها على الإنترنت بسهولة: ترجمة -وبتصرف- للمقال Baymax in CSS
  4. نستخدم نحن المطوّرين ومُصمّمي الواجهات CSS في التنسيق والتَمَوْضُع (positioning)، وفي إنشاء مواقع تتسم بالجماليّة والمظهر الخلّاب، ونستخدمها غالبًا في إضافة الحركة إلى الصفحات باستخدام التنقّل (transitions) أو التحريك (animations)، ولكنّنا عادةً لا نتعمّق، ولا ندخل في خفايا خاصّيات CSS المُعقّدة. يُمكن للتحريك أنّ يكون أداةً قويّة في مُساعدة زوّار مواقعنا وعُملائنا على فهم تصميم الموقع بالشكل الصحيح، ولذلك يوجد بعض المبادئ والتي بتطبيقها يمكن الاستفادة من التحريك بالشكل الأمثل. إنّ هذه المبادئ ليست بالجديدة، وهي عبارة عن مُمارسات عمليّة وتجارب طويلة من عالم ديزني، فقد نُشرت هذه المبادئ الاثنا عشر للتحريك بكتاب وهو بعنوان: "وهم الحياة: الرسوم المُتحركة في ديزني" في عام 1981، وصفت وصوّرت هذه المبادئ كيف يُمكن للتحريك أنّ يُستخدم في سلب عقل المُشاهدين في عالم وهميٍّ قابل للتصديق. سأتناول في هذه المقالة، كلًا من المبادئ الاثنا عشر، ومُناقشة كيف لها أنّ تُطبّق في صناعة صفحات الويب مُستخدمًا الأمثلة التوضيحيّة، وإتاحة الوصول إلى مصدر شيفرة HTML و CSS الخاصّة بهذه الأمثلة عبر حساب الأكاديمية في Github. التمدّد والانكماش (Squash and Stretch) إنها المفهوم القائم على أنّ للأجسام كتلة فيزيائيّة، وبتحركها يجب أن تبقى الكتلة ثابتة دون أن تتغيّر، فستتوسّع الكرة عندما تصطدم مع الأرض، ولكنّها أيضًا ستصبح أقصر باعتبار أنّ كتلتها سيُعاد توزيعها. يُمكن الاستفادة من هذا المفهوم عند إنشاء الكائنات الّتي نُريدها أنّ تبدو فيزيائيّة، مثل الأشخاص، الأشياء، أو تنطط الكرات. يُمكن تجاهل هذه المبدأ عند التعامل مع عناصر صفحة الويب، فلا ترتبط عناصر الـ DOM بالضرورة مع الأجسام الفيزيائيّة، ويُمكن لها أنّ تكبر وتتقلّص على المُتصفّح كما تقتضي الحاجة، فعلى سبيل المثال، يُمكن للزر أنّ يكبر ومن ثم يتلاشى، أو يُمكن لرسائل الخطأ أنّ تظهر وتختفي كما يحلو لها. ولكن في حقيقة الأمر، يُمكن الاستفادة من مبدأ التمدّد والانكماش في إعطاء الكائن أو الجسم صفات الكتلة الفيزيائيّة، ويُمكن للتغيرات الصغيرة في الشكل إنشاء تأثيرات طفيفة ولكنّها في نفس الوقت مُلفتة للنظر. التهيئة (Anticipation) لا تحدث الحركات فجأةً، ففي الواقع العمليّ، تَنتج الحركة عادةً تدريجيًا، سواءً كان ذلك في دوران الكرة قبل السقوط من على الطاولة، أو عندما يثني شخصٌ ما قدميه استعدادًا للقفز. يُمكننا استخدام ذلك في جعل التحوّل (transitions) والتحريك (animations) في CSS أكثر حيويّةً وواقعيّة، ويُمكن لهذا المبدأ أنّ يكون على شكل ارتداد خفيف للكرة، ليُساعد المُستخدم على إدراك ما الّذي يتغيّر ويتتبّع مسار الجسم على الشاشة. فعلى سبيل المثال، يُمكن لعنصر من عناصر الصفحة أنّ يتقلّص قليلًا قبل أنّ يكبر في الحجم عند حركة المرور (hover)، أو لنقل مثلًا عند إضافة عناصر قائمة (items) جديدة إلى قائمة، فيُمكن أنّ يُمهد لهذه الحركة عبر إبعاد باقي العناصر وإفساح المجال لها أوّلًا. التقديم (Staging) يتأكّد هذا المبدأ من أنّ الجسم أو الشيء هو عنصر المشهد الرئيسي، وهو عندما تفسح باقي الأجسام الأخرى أو جوانب المشهد المجال لمكان حدوث الفعل الرئيسي، يعني هذا إما وضع الفعل الرئيسي في مكان بارز للعيان، أو حجب باقي العناصر بهدف التركيز على ما يجب للمُستخدم أنّ يراه. إن أردنا قولها بلغة ومُصطلحات الويب، فإن أحد الأساليب قد يكون في استخدام تغشية لمُحتوى مُعيّن دون آخر، أو ربما إضافة طبقة داكنة على الصّفحة، ومن ثُمّ وضع المُحتوى في الواجهة ليَظهر هذا المُحتوى بارزًا للنظر والاهتمام. يُمكن استخدام أسلوب آخر وهو الحركة، فعندما تتحرّك أجسام عدّة، فمن الصعب معرفة أي منها جديرٌ بالاهتمام والمُتابعة، ولكن إنّ توقّفت جميع التحركات وجسم واحد تحرّك، ولو بحركة صغيرة، فمن السهل جدًا اكتشافه. يُستخدم هذا الأسلوب عادةً مع زر الحِفظ (save)، بحيث يتذبذب أو يتمايل أو يومض بخفّة ليوضّح للمُستخدم أنّ عليه حِفظ المُستند قبل المُتابعة، مع الحفاظ على بقية أجزاء الصفحة ساكنة وبدون أدنى حركة، مع العلم أنّ أي حركة ولو طفيفة ستبرز وتكون واضحة للعيان. الحركة المُفصّلة والحركة من توقّف إلى توقّف (Straight-Ahead Action and Pose-to-Pose) إن الفعل straight-ahead يكون عندما يتمّ رسم كل إطار صورة (frame) لإتمام التحريك، أما الفعل pose-to-pose (توقّف إلى توقّف) يكون عندما يتمّ رسم سلسلة من الإطارات المفتاحيّة (keyframes) وتُرسم الفترات فيما بينها لاحقًا، عادةً من قِبل مُساعد. يُستخدم في عالم الويب معظم الأحيان التحريك من نوع pose-to-pose، فمثلًا الانتقال (transition) بين الإطارات المفتاحيّة (keyframes) يُمكن أنّ تتم معالجتها من قبل المُتصفّح، والذي يُقحم الاختلاف بين كل إطار ويرسم عددًا منها أيضًا بهدف جعل التحريك أكثر سلاسةً وواقعيّة. يوجد استثناء وحيد، وهو دالة التوقيت steps، فمع هذه الدالة، سيخطو المُتصفّح خطوات على عدد الإطارات المُحدّدة، وبهذه الطريقة ستتمكن من رسم سلسلة من الصور وجعل المُتصفّح يعرض كل منها تتابُعيًا، ليُنشئ بذلك حركة بالأسلوب **Straight Ahead Action”. توابع الفعل وتداخله (Follow Through and Overlapping Action) لا تحدث الأشياء دائمًا في نفس الوقت، فعندما تتوقّف سيارة فجأةً، فإنّها تميل إلى الأمام، مع تصاعد الدخان نتيجة احتكاك العجلات مع الأرض، ومن داخل السيارة يواصل السائق ميلانه نحو الأمام إلى حين توقّف كل حدث بشكل مُنفصل. إن هذه التفاصيل ما هي إلا أمثلة على توابع الحركة وتداخل الحركة، ويُمكن استخدام هذا المبدأ على الويب للمُساعدة على التأكيد أنّ شيئًا ما قد توقّف الآن لأنّه يجب أن يتوقّف، وليس أنّه قد توقّف عن التحريك بشكل مُطلق، على سبيل المثال، عنصر قائمة أُضيف إلى القائمة قد ينزلق، ليتقدّم شيئًا ما أكثر من اللازم، ومن ثُمّ يُصحّح نفسه إلى التَمَوْضُع الصحيح. إن إنشاء حركة ذات طابع تداخلي، يتطلّب إنشاء عناصر تتحرّك خطًا مُختلفة وذات فروقات طفيفة عن بعضها البعض، وفي الحقيقة هذا الأسلوب مُستخدم بشكل جيّد في أنظمة التشغيل iOS، فعندما يتمّ التنقل بين صفحات التطبيق، بعض الأزرار والعناصر ستتحرّك بمُعدّل مختلف عن بعضها، ليظهر التأثير الكلي في النهاية بشكل مُفعم بالمرونة والسلاسة وأقل سطحيّة من إذا كان كلُ شيءٍ يتحرّك دفعة واحدة وبنفس المُعدّل، وهذا التنقل المتوحد في كينونة واحدة يُعطي المُشاهد أو المُستخدم فترةً زمنيّة ليُدرك هذا التغيير الحاصل بالشكل المطلوب، والابتعاد عن الالتباسات. قد يُستخدم هذا الأسلوب في عالم الويب عبر تجميع التنقلات (transitions) أو التحريك (animations) تتابعيًا، بهدف إنشاء تأثيرات تظهر بمُعدّل سرعة مُختلف فيما بينها. التباطؤ والتسريع (Slow In and Slow Out) لا تنتقل الأجسام من السكون التام إلى السرعة القصوى فورًا، بل تميل الأجسام إلى رفع السرعة تدريجيًا، والتَبْطيء منها قبل التوقّف، فبدون التسارع والتباطؤ، ستكون الحركة وكأنها حركة آلة (روبوتي) يُعرَف التباطؤ والتسريع في عالم CSS بالمُصطلح easing (تسهيل)، ويُستخدم كدالة توقيت (timing function)، وهو طريقة في وصف وتحديد مُعدّل التغيّر خلال مسار التحريك. يُمكن وباستخدام دالات التوقيت جعل الأجسام المُتحركة تبدأ بطيئةً وترفع من السرعة (الدالة ease-in)، أو تبدأ سريعةً وتخفّف من السرعة (الدالة ease-out)، ويُمكن من أجل التأثيرات الأكثر تعقيدًا استخدام دالّة التوقيت cubic-bezier. التقوّس (Arc) لا شك أنّ الأجسام ستبدو أكثر حيويّة باستخدامها حركات التباطؤ والتسريع المُتبعة في المبدأ السابق، ولكن في حقيقة الأمر إن الأجسام نادرًا ما تتحرك بحركة مستقيمة، فهي تميل إلى اتباع انحناءات مقوّسة. يُمكننا تحقيق هذه النوع من الحركات المُقوّسة مع CSS بطريقتين، تكون الطريقة الأولى بالجمع بين أكثر من تحريك، فالحركة الخاصّة بتنطط وارتداد الكرة، يُمكن تطبيقه عن طريق عمل تحريك أوّل يجعل الكرة تتحرّك صعودًا ونزولًا، بينما تحريكٌ ثاني يجعل الكرة تتحرّك إلى جهة اليمين في نفس الوقت، عندها ستظهر الكرة عبر الشاشة وهي ترتد من الأرض وبشكل مقوّس. تكون الطريقة الثّانية عبر تدوير العنصر نفسه، حيثُ بإمكاننا التعديل على مركز دوران الجسم عبر ضبط مبدأ التغيّر (transform origin) ليُصبح خارج جسم العنصر، فعندما ندوّر الجسم، فإنه سيدور في تقوّس. الفعل/الحدث الثانوي (Secondary Action) بينما الحدث الرئيسي يحدث، يُمكن لحدثٍ ثانويٍ أن يُساعد على التأكيد منه أو حتَّى أنّ يزيد عليه، ربما على سبيل المثال، تأرجح ذراعي شخص يمشي (المشي حدث رئيسي والتأرجح حدث ثانوي) أو تنطط كرة (حدث رئيسي) مع ظهور بعض الغبار (حدث ثانوي) عند الارتطام. يُمكن رؤية هذا المبدأ على مواقع الإنترنت، عندما تبعد العناصر من نفسها لإفساح المجال للعنصر الجديد، كما يحدث عند سحب عنصر قائمة ووضعه في منتصف القائمة. التوقيت (Timing) إن توقيت التحريك هو الوقت المُستغرق في إتمام حركته، فيُمكن للتوقيت أنّ يُستخدم في جعل الأجسام الوزنة تبدو بطيئة في حركتها، أو في إضافة طابع مُميّز وحيوي في الحركة نفسها. إن التعديل وتسوية/ضبط الوقت في صفحات الويب بسيطٌ للغاية، فكل ما يتطلب فعله هو التعديل على قيمتي الخاصيتين animation-duration أو transition-duration. المُبالغة (Exaggeration) يُستخدم أسلوب المُبالغة بشكل كبير مع أفلام الرسوم المُتحرّكة، فيُمكن باستخدامه جذب نظر المُشاهد إلى حركات أو أفعال مُعيّنة، لتجعل هذه المُبالغة من الرسومات أكثر إثارة أو ربما في بعض الأحيان أكثر هزليّة، فعندما يُحاول الذئب الانقضاض على فريسته، فربما يجعل الرسام من فكاه مفتوحان على مصراعهما أكثر من المُعتاد بهدف إضافة شيء من الرعب أو الهزليّة إلى المشهد. وفي صفحات الويب، يُمكن للأجسام أنّ تتوسّع وتتقلّص بهدف التأكيد عليها وجذب الانتباه إليها، على سبيل المثال عند ملئ نموذج ما (form)، فيُمكن للقسم النشط أنّ يكبر بينما بقية الأقسام تنكمش أو تتلاشى (fade). الرسم المتين (Solid drawing) عند تحريك الأجسام في الأبعاد الثلاثة (three dimensions)، يجب أنّ يكون الاهتمام مُنصبًا على أنّ هذه الأجسام تتبع قواعد الرسم المنظوري، فالناس مُعتادة على العيش والتعامل مع عالم ثلاثيّ الأبعاد، ولذلك عندما لا يبدو على الأجسام كما لها أنّ تكون في الواقع، فستبدو للمُشاهد غريبةً وغير مقبولة. تدعم آخر إصدارات المُتصفّحات الأبعاد الثلاثيّة جيّدًا، يعني هذا أنّه يُمكننا تدوير وتوضيع الأجسام في الصفحة ليتولّى المُتصفّح عمليّة التحوّل بنفسه. عامل الجذب (Appeal) إن عامل الجذب هو خصائص ومُميّزات العمل الفني وكيف يُمكن له أنّ يجعل منا مُتصلين ذهنيًّا مع مقصد ونيّة الفنان، فهو كجاذبيّة المُمثّل (الكاريزما)، ففي النهاية الانتباه إلى التفاصيل واتحاد الحركات مع بعضها البعض تناغميًا تجعل من النتائج نتائج مُميّزة وذات ظهور خلاب. يُمكن للتحريك المصنوع بأيدٍ احترافيّة وبعناية خاصّة أنّ يُنشئ جاذبيّة ومظهر ذو شأن على صفحات الويب، وقد أدركت بعض الشركات ذلك، فاستفادت Stripe من التحريك وسخرته في إضافة مصداقيّة إلى شاشة الدفع (checkout) الخاصّة بهم. استخدم التحريك إن استخدام المبادئ السابقة له فضلٌ كبير في تحسين التحريك، فالرسوم الّتي تحافظ على الوزن الفيزيائي للأجسام والتغييرات ذات الطابع الحدسي، وتستفيد من الحدث الثانوي مع التوقيت المُناسب سيجعل منها ذو جودة عالية لُساعد في تقديم إضافة نوعيّة وذات جودة إلى المُحتوى. يُنصح، وعندما تكون الفرصة سانحة، في إضافة بعض من التحريك والرسوم إلى صفحات الويب، وخاصّة مع استخدام هذه المبادئ، والّتي ستُضيف شيئًا من الجماليّة والجاذبيّة للموقع ليتميّز عن بقيّة أقرانه. ترجمة – وبتصرّف– للمقال Animation Principles for the Web.
  5. حدّث تويتر مؤخرًا تصميم زر التفضيل "fave" الخاصّ به، وذلك بتقديم تحريكٍ جديد، وبدلًا من الاعتماد على التنقل transitions في CSS، فإن التحريك المُستخدم يعتمد على استخدام سلسلة من الصور، في هذا الشرح سيتمّ إعادة إنشاء التحريك باستخدام CSS وبدالة التوقيت steps. وهم الحركة (Illusion of movement) يُشبه هذا التأثير إلى حدٍ كبيرٍ التأثير المُقدّم بواسطة أجهزة Zoetrope القديمة، حيثُ تعرض سلسلة من الرسومات في حلقة وحول أسطوانة، ولكن ما سيتمّ استخدامه هنا هو عرض سلسلة مُسطّحة من الصور داخل عنصر. عرض المثال مثال على تحريك الزر عند حركة المرور hover: .twitter-fave { width: 70px; height: 50px; background: url("//raw.githubusercontent.com/HsoubAcademy/HsoubAcademy.github.io/master/examples/CSS-animation-series/Twitter%20fave%20animation/twitter_fave.png") no-repeat; background-position: 0 0; } .twitter-fave:hover { background-position: -3519px 0; transition: background 1s steps(55); } يمكن معاينة الملفات المصدرية لهذا الدرس على حساب أكاديمية حسوب على Github. تمّ في البداية إنشاء سلسلة من الصور، والّتي ستُشكل التحريك في نهاية الأمر: يجب وضع هذه الصور/الإطارات على صفّ واحد بهدف إتمام عمليّة التحريك بسهولة أكبر، ليتمّ عندها التحويل من الصورة الأولى إلى الصورة الأخيرة، وذلك عبر التحكم بمكان الخلفيّة باستخدام شيفرة CSS. كيف ستتموضع صور الخلفيّة background image ضمن العنصر: دالة التوقيت ()steps كما هو الأمر مع مُعظم دالات التوقيت مثل ease أو cubic-bezier، فإن الانتقال transition يُحرّك العنصر بسلاسة بين حالة البداية وحالة النهاية، أما دالة التوقيت steps فهي مُختلفة، فبدلًا من ذلك الانتقال (بين نقطتين)، سيتمّ تقسيم التحوّل/الانتقال إلى عدد من الخطوات والتحكم بين هذه الخطوات بشكل مُنفصل. تمثيل دالة ()steps بالرسم البياني، والّتي تَظهر على شكل سلسلة من الخطوات: البداية مع إعداد HTML: <section class="fave"></section> صورة الخلفيّة Background image سيتمّ في الخطوة التّالية تنسيق العنصر السابق وإضافة تَمَوْضُع لصورة الخلفيّة background image: .fave { width: 70px; height: 50px; background: url(images/twitter_fave.png) no-repeat; background-position: 0 0; } سيتمّ إضافة تنسيق لحركة المرور hover، ليتم نقل تَمَوْضُع الخلفيّة إلى نهاية سلسلة الصّور: .fave:hover { background-position: -3519px 0; transition: background 1s steps(55); } تمّ في الخاصّيّة الثانية تعيين قيمة للانتقال transition، وذلك للخاصية background وبمدة انتقال ثانية واحدة، ولدالة التوقيت ()steps القيمة 55، وذلك لأن عدد الصور الكلّي الّتي سيتمّ التبديل بينها هو: 55. لن يحدث التحريك إلّا عند حركة المرور hover، حيثُ سيتمّ الانتقال عبر جميع الصور وبعدد خطوات متساوي (55 خطوة). لماذا لا يتمّ استخدام gif مع التحريك؟ يُمكن في الحقيقة استخدام الصور المُتحركة (gifs)، ولكن لن تكون الاختيار الأمثل في هذه الحالة، حيثُ حجم الملفّ سيكون أكبر، ومن الصعب التحكم بمُعدّل النقل، ولكن بالطريقة المُستخدمة هنا يُمكن عمل: إيقاف مؤقت، إعادة التحريك، وإجراء كافّة التعديلات المطلوبة لإتمام التحريك على الوجه المطلوب. استخدامات أخرى للدالة steps إن تحريك الصور من نوع sprites هو أحد استخدامات دالة التوقيت steps، فأي شيء يحتاج إلى التحريك على شكل سلسلة من الخطوات المُفصّلة، يُمكن له الاستفادة من هذه الدالة. أقصوصة الغش (Cheatsheet) تقدّم الأقصوصة التّالية مُختصر للمقالة، والذي يُمكن الرجوع إليه عند تطبيق الدرس. خاتمة ما أجمل التحريك في صفحات الويب؛ سرعة، خفّة، مرونة، جمال، أنصح بالقراءة عن الأمر والتعمّق في جنباته، فهو الوجه الجديد لصفحات الويب. ترجمة وبتصرّف للمقال Twitter’s "fave" animation.
  6. سنتكلم في هذا المقال عن أفضل مكاتب التحريك في ‏CSS، والتي تساعدك في حفظ وقتك عند تصميم ‏موقع الويب الخاص بك من خلال استخدامك لهذه المكاتب التي تضفي بعض الديناميكية والتفاعل إلى ‏عملك، حيث تحوي هذه المكتبات على العديد من عناصر ‏التحريك والمؤثرات لأي نوع من أنواع عناصر صفحات الويب كالنصوص، الصور، الإطارات، الأزرار، والبطاقات والعديد غيرها. إن لمكاتب التحريك في CSS العديد من الأنماط styles والتي تستخدم تأثيرات خاصة بها (يمكن الإطلاع على المزيد في CSS effects)، وبالتالي مهما كان النمط الذي تبحث عنه سواء بسيط وسهل، أو ممتع مؤثر ستجد مكتبة مفيد لك. تتنوع المؤثرات من المنزلقات إلى التلاش والدوران كما يوجد العديد من التأثيرات الأكثر عمقًا وتخصيصًا مثل مؤثرات النبض، ودقات القلب وغيرها... باختصار هذه المكتبات توفر لك ماتريده، ويمكن تثبيتها بسهولة داخل موقعك كما أن غالبيتها خفيفة الحجم ومُتجاوبة responsive. Hexa تعتبر Hexa مكتبة مذهلة للتحريك، بسيطة وخفيفة الحجم. يمكن استخدام مؤثرات التحريك التي تقدمها لإحياء عناصر صفحة الويب من نصوص، صور، أيقونات وبقية العناصر الأخرى. Vivify إن Vivify هي مكتبة تحريك CSS مجانية تستطيع من خلالها إضافة المؤثرات إلى الأزرار، الصور وغيرها، وتحوي على العديد من المؤثرات التي يمكن الاختيار فيما بينها مثل الكرة، النبض، الاصطدام من اليمين واليسار، الاهتزاز، الانفلات، القفز، التلاشي، الدوران الشاقولي، السحب، الطي... Tachyons-animate تعتبر Tachyons-animate مجموعة من صفوف CSS ذات الهدف المحدد وهو تنسيق الحركة باستخدام CSS. في حال كنت تريد الحصول على أكثر من مجرد تحريك فباستطاعتك استخدام هذه الأداة لأنها لاتحوي على أي مؤثرات مُحددة مسبقًا وإنما تحوي على صفوف CSS فقط تستخدمها ضمن موقعك تبني من خلالها الحركة التي ترغب بها ولكنها توفر عليك الكثير من الوقت. ‏Infinite – useful CSS animations تعتبر Infinite-useful CSS animations مجموعة صغيرة من عناصر التحريك المفيدة للغاية والتي يمكن استخدامها لتوليد عناصر نابضة بطريقة التحكم بشفافية ومقدار التوسع في العناصر، إنشاء رسوم متحركة للتنبيه، تدوير العناصر وغيرها. Motion UI تعتبر Motion UI مكتبة Sass قوية تفيد في إنشاء التحريكات والانتقالات، وقد أوجدت هذه المكتبة بالأساس كمكون ضمني في Foundation لتصميم البرامج، ولكن يمكن استخدامها كمكتبة منفصلة الآن، حيث يمكن استخدامها في إضافة تأثيرات السرعة، الانزلاق، تغيير الحجم وغيرها.. DynCSS إن DynCSS هي مكتبة عظيمة تستخدم في التحريك والتي تقوم بتفسير الـ CSS الخاص بك من أجل إنشاء قواعد dyn بسيطة وديناميكية تبث الحياة في موقعك. All animation تعتبر All animation.css أداة تحوي العديد من عناصر التحريك الممتعة لجعل مشروعك أكثر تفاعلية وجاذبية بالنسبة للمستخدم، وهي عبارة عن عدة مؤثرات وعناصر تحريك ممكن استخدامها لإضافة تأثيرات ‏‎3D‎‏ وغيرها. Animate.CSS إن Animate.CSS هي مكتبة تحريك أخرى تعمل على جميع المتصفحات وتُستخدم لإضافة مؤثرات مثل الاهتزاز، ‏الاضطراب، النبض، التأرجح، التمايل..‏ Hover.CSS تعتبر Hover.CSS مجموعة CSS3 خاصة بتأثيرات التأرجح hover effects وتُستخدم على الروابط ، الأزرار، الشعارات، SVG، الصور وغيرها من العناصر. كما أنها متوفرة كـ CSS، Sass، و LESS. Effect.CSS تعتبر مكتبة Effect.CSS مكتبة CSS تُستخدم لإضاف انتقالات حساسة للموقع بهدف تحسين تجربة المستخدمين، حيث تقوم بإنشاء انتقالات CSS وتحريكات للأزرار، القوائم، الانتقالات بين الصفحات، العناوين، التلميحات، علامات التبويب، الإطارات وغيرها... ‎Magic CSS تحوي Magic CSS على عناصر تحريك CSS3 بمؤثرات خاصة تضفي روحًا خاصة للموقع مثل المؤثرات السحرية، المؤثؤات الساكنة، المناظير، الدوران، التحجيم، الانزلاق.. CSSHAKE إن CSSHAKE هي مجموعة من صفوف CSS لتحريك عناصر الصفحة DOM، وتثبيت هذه المكتبة سهل للغاية حيث يمكن تنزيل ملفات منفصلة لكل تأثير تحريك، توسيع، أو تصغير. Repaintless CSS تعتبر Repaintless CSS مكتبة CSS خاصة بالتحريك خفيفة الحجم تحوي عشرات المؤثرات التي تجعل الموقع أكثر فاعلية بدون التأثير على سرعته، حيث يمكنك إضافة مؤثرات الانزلاق بكل سهولة. Tuesday إن Tuesday هي مكتبة CSS منفصلة تستخدم لإضافة تأثيرات الدخول والخروج مثل التمدد والتقلص، الهبوط، نزول المطر، المفصلات. Obnoxious تحوي Obnoxious تأثيرات ممتعة ولكن قد لاتناسب جميع المواقع ولكن بالتأكيد في حال استخدامها ستجعل موقعك يبرز بين المواقع الأخرى. من هذه المؤثرات الاهتزاز، زيادة الحجم، الطي، الالتواء... Flutter – CSS Image Hover Effects & Lightbox تحوي مكتبة Flutter على 12 مؤثر تحريك خاص بالتأرجح hover فوق الصور، أنظمة الأعمدة الثنائية أو الثلاثية، بالإضافة إلى 4 أنواع من الإضاءة وغيرها. Skloading – CSS3 Animations تعتبر Skloading مكتبة تحريك CSS3 بتصميم قابل للتخصيص بشكل كامل حيث يمكنك تحميل واستخدام هذه التحريكات الخاصة بهذه المجموعة ضمن مشروعك. Viavi CSS3 Scroll Effects يمكنك من خلال Viaviتجربة مجموعة المغازل ‏spinners‏ والمحملات ‏loaders‏ التي يمكن استخدامها لجذب انتباه ‏المستخدم، وهي تصميمات مُتجاوبة بشكل كامل كما أنها تتكيف بشكل رائع مع أي حجم للشاشة. CSS Bubbles and Tooltips إن هذه المكتبة ( يمكن الإطلاع على المزيد من خلال CSS Bubbles and Tooltips) تقدم لك التلميحات والفقاعات في CSS والتي ستساعدك في حفظ الوقت، حيث ستجد مجموعة من أشكال الملاحظات جاهزة على شكل مربع أو غيوم أو فقاعات على شكل قلب وكذلك تلمحيات للموقع، النصوص، الواجهات، الشرائط والأزرار. ‎ Animatia – CSS Image Hover Effects إن Animatia هي مكتبة خاصة بتأثيرات التأرجح hover التي تحدث للصور أو عناصر CSS أخرى مثل الأزرار وغيرها. CSS Box and Text Shadows يمكنك تنزيل صناديق CSS و ظلال النصوص (للإطلاع CSS Box and Text Shadows) واستخدامها مباشرة في موقعك وهي عبارة عن مجموعة فيها 40 تأثير ظلال يمكن تطبيقها على النصوص، الأزرار، الصور وغيرها. HoverMe تعد HoverMe مجموعة رائعة من عناصر تحريك CSS3 التي تحوي 4 صور أزرار، 10 أزرار تحميل، و 8 تحريكات متقدمة وغيرها. ‎Wickedcss إن Wickedcss هي مكتبة تحريك CSS3 تمنحك المتعة في التعامل معها فهي تحوي العديد من المؤثرات مثل التقافز pound، الانزلاق، النبض، دقات القلب، الدوران Woah إن مكتبة Woah هي لمطوري الويب غريبي الأطوار، حيث يمكن استخدامها لإضافة تحريكات مميزة لأي عنصر من عناصر صفحة الويب. Motion CSS تعتبر Motion CSS مكتبة تحريك ممتعة وسهلة التثبيت فلا تحتاج لاستخدامها سوى إلى ربطها مع ملف CSS ثم يمكنك استخدام صفوف محددة لأي عنصر من عناصر الصفحة لتحريكه. ترجمة -وبتصرّف- للمقال 25 Best CSS Animation Libraries لصاحبه Iggy مصمم موقع Line25
  7. إذا طبّقنا بضعة انتقالات (transitions) على عناصر الصفحة فقد تؤدي إلى نتيجة رائعة إذا خططنا لها جيدًا، وسنتعلم في هذا المقال كيف نستخدم الانتقالات لدب الحياة في محتوى الصفحة، وسنخطط ونبني تأثيرات مرور الفأرة فوق العناصر لتبدو بأجمل مظهر. الانتقالات أم الحركات الانتقالات (transitions) رائعة للانتقال بسلاسة من حالة إلى أخرى (والعودة إلى الحالة الأصلية مجددًا) في المتصفح، وقد تبدو أنها بديلٌ أبسط من الحركات (animation) التي تستعمل keyframes و animation، لكن لكلٍ ميزاتها وفوائدها. فمثلًا، لن تستفيد من الانتقالات إذا كنت تريد حدوث حركة عند تحميل الصفحة، أو إذا أردتَ أن تستمر الحركة طوال الوقت؛ أما إذا كانت لديك حالتين وأردتَ التحريك بينهما بسهولة فستستفيد حينئذٍ من الانتقالات. إذا كنتَ مهتمًا بالفروقات بين الانتقالات والحركات فأنصحك بمراجعة هذه المقالة. سنبني في هذا الدرس مشهدًا من الفضاء وسنضيف إليه تأثير مرور الفأرة فوقه لعرض بعض المعلومات الإضافية عن الكوكب، وسنفِّكر بحالتَي العناصر وما هي الخاصيات التي سنستخدمها للحصول على انتقال سلس وجميل. يمكنك الاطلاع على المثال الكامل لأخذ فكرة عن ما سنفعله. See the Pen &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;a data-cke-saved-href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io/donovanh/pen/qmNgXW/&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39; href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io/donovanh/pen/qmNgXW/&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;Planet hover effect part 3: with transition&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;/a&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt; by Donovan Hutchinson (&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;a data-cke-saved-href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io/donovanh&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39; href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io/donovanh&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;@donovanh&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;/a&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;) on &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;a data-cke-saved-href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39; href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;CodePen&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;/a&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;. ضبط الحالتين أكثر الأمور التي تأخذ وقتًا وجهدًا عند إنشاء الانتقالات هي الحالة الأولية والحالة النهائية للعنصر، فيجب أن نُفكِّر كيف سيبدو العنصر قبل تطبيق الانتقال وماذا يجب أن يتغيّر في مظهره بعد حدوث الانتقال. عندما أُنشِئ الانتقالات المعقدة نسبيًا فلا أهتم بالحركة نفسها إلى أن يعجبني مظهر العناصر في الحالتين، ومن هذا المنطلق فسنهتم بالخاصيات التي سنستخدمها في حالة hover لأن هذه الخاصيات ستخضع إلى حركة. قبل الخوض في موضوع الانتقالات فلنضبط الحالتين أولًا. حالة البداية سيكون كوكب الأرض في منتصف المشهد بدايةً، وسيدور القمر حوله. شيفرة HTML تتضمن عنصر article الذي نضع فيه عنصرَي earth و moon، لاحظ أنَّ عنصر moon موجود داخل حاوية باسم moon-container لأنها ستساعدنا بموضع القمر لاحقًا. <article class="earth-demo"> <div class="earth"> <img src="https://cssanimation.rocks/images/random/earth.png"> </div> <div class="moon-container"> <div class="moon"> <img src="https://cssanimation.rocks/images/random/moon.png"> </div> </div> </article> هذه هي أنماط CSS التي سنستخدمها، سنجعل موضع العنصر earth مساويًا للقيمة absolute وسنستخدم الدالة calc لتوسيط الأرض رأسيًا وأفقيًا. .earth { position: absolute; top: calc(50% - 100px); left: calc(50% - 100px); } وسنُحدِّد موضع الصورة ونعطيها طولًا وعرضًا: .earth img { height: 200px; position: absolute; top: 0; left: 0; width: 200px; } وسنفعل المثل تقريبًا للقمر، إذ سنبدأ بوضع الحاوية في منتصف الشاشة: .moon-container { position: absolute; top: calc(50% - 25px); left: calc(50% - 25px); } ثم سنضبط أبعاد القمر ونُطبِّق الحركة spin عليه (والتي سنعرِّفها لاحقًا)، وهذا ما سيجعل القمر يدور حول الأرض. .moon { animation: spin 20s linear infinite; background: none; height: 50px; pointer-events: none; transform-origin: 25px; width: 50px; } عند هذه المرحلة سيكون القمر متموضعًا في منتصف الشاشة وفوق الأرض، لذا لنستخدم الخاصية transform لتحريك القمر إلى خارج الحاوية الخاصة بعيدًا عن الأرض. .moon img { height: 50px; transform: translateX(-160px) translateY(-160px); width: 50px; } هذا يعني أنَّ عنصر moon سيدور فوق الأرض، لكن الصورة ستدور حول الأرض. لنضف الآن حواف مدورة للعنصر لكي تظهر حواف الأرض والقمر بدقة وسنستعمل الخاصية box-shadow لإعطائهما توهجًا أزرقًا: .earth img, .moon img { border-radius: 50%; box-shadow: 0 0 12em 1em rgba(110, 140, 200, .6); } في النهاية، سنُعرِّف الحركة spin لتدوير القمر، وهذه الحركة بسيطة، إذ سندوِّر القمر حول المحور Z بزاوية 360 درجة. @keyframes spin { to { transform: rotateZ(360deg); } } هذا هو ناتج هذه المرحلة: See the Pen &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;a data-cke-saved-href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io/donovanh/pen/aWZPeP/&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39; href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io/donovanh/pen/aWZPeP/&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;Planet hover effect part 1: initial stage&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;/a&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt; by Donovan Hutchinson (&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;a data-cke-saved-href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io/donovanh&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39; href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io/donovanh&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;@donovanh&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;/a&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;) on &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;a data-cke-saved-href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39; href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;CodePen&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;/a&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;. عرض المزيد من المعلومات نريد أن نظهر معلومات مفيدة حول كوكب الأرض عند مرور الفأرة فوقه، ربما ستساعد هذه المعلومات الفضائيين في معرفة بعض الأمور الأساسية عن كوكبنا قبل أن يزورونا :-) . علينا قبل ضبط حالة hover أن نضيف هذه المعلومات، وسنبدأ بإضافة عنصر div ذي المعرِّف more-info الذي يحتوي على بعض النصوص: <article class="earth-demo"> <div class="earth"> <div class="more-info"> <h1>Earth</h1> <ul> <li>Third planet from the Sun</li> <li>Atmosphere: 21% oxygen</li> <li>Liquid water on surface</li> <li>Only planet that has life (that we know of)</li> </ul> </div> <img src="https://cssanimation.rocks/images/random/earth.png"> </div> <div class="moon-container"> <div class="moon"> <img src="https://cssanimation.rocks/images/random/moon.png"> </div> </div> </article> أضفنا هذه المعلومات داخل حاوية earth لأننا نريد جعلها جزءًا من التأثير، أي عند مرور الفأرة فوق النص فسيبقى على الشاشة. سنضيف بعض أنماط CSS إلى عنصر more-info: .earth .more-info { background-image: linear-gradient(to bottom, rgba(10,10,10,1), black); border-radius: 1em; color: #fff; opacity: 0; padding: 1em; transform-origin: 0 0; transform: scale(.8); width: 400px; } .earth .more-info h1 { margin: 0 0 1em; text-align: right; } ضبطنا هنا لون الخلفية والحواف المنحنية والحاشية وعرض العنصر، وغيّرنا قياسه قليلًا باستخدام transform وضبطنا transform-origin إلى الزاوية العليا اليسرى لكي يتغيّر قياسه بدءًا من تلك النقطة. خاصية opacity للعنصر more-info تساوي الصفر أي أنَّ العنصر شفاف تمامًا ولن يكون مرئيًا، وقد نضيف الخاصية visibility لكي نضمن أنَّ المحتوى لا يتداخل مع بقية العناصر، لكننا لن نفعل ذلك في مثالنا هذا. إنشاء انتقال للخاصيات المطلوبة عندما نضبط تأثير الانتقال فمن المهم أن نأخذ الأداء بالحسبان، فبعض الخاصيات مثل الارتفاع والحاشية (padding) وحجم الخط و background-position لن يكون أداؤها جيدًا إذا أجرينا تأثير الانتقال عليها، والسبب وراء ذلك هو أنَّها تجعل المتصفح يُعيد حساب الكثير من التفاصيل في تخطيط الصفحة عندما تتغير. لذا من الأفضل استخدام الخاصيتين opacity و transform عند إجراء حركات لأن أداءها جيد ولا تسبب «تعليق» في المتصفح. سنستخدم في هذا المثال الخاصيتين opacity و transform إذ سيُصغَّر العنصر more-info قليلًا باستخدام transform وكان شفافًا تمامًا (قيمة opacity تساوي الصفر). أما في حالة hover فسنغيّر شفافية العنصر more-info لكي يصبح مرئيًا وسنزيح الكوكب إلى الجانب. حالة مرور الفأرة فوق العناصر لنبدأ بضبط حالة ‎.earth:hover، إذا كنتَ ستستخدم Sass فيمكنك اختصار الكثير من الشيفرات التي سنكتبها، لكنني سأستخدم CSS في هذا الدرس. لنحرِّك الكوكب جانبًا بادئ الأمر: .earth:hover img { transform: translateX(-75px) translateY(-75px) scale(.5); } خاصية transform السابقة ستدفع الكوكب إلى اليسار بمقدار 75 بكسل وستصغره إلى 50% من حجمه. لنقم بشيءٍ مشابه إلى القمر: .earth:hover ~ .moon-container { transform: translateX(-75px) translateY(-75px) scale(.5); } .earth:hover ~ .moon-container img { transform: translateX(-140px) translateY(-140px); } نفّذنا خدعةً هنا إلى صورة القمر ألا وهي استخدام transform لتقريبه إلى الأرض. لنُظهِر الآن العنصر more-info: .earth:hover .more-info { opacity: 1; transform: none; } ضبطنا الشفافية إلى 1 وهذا يعني أنَّ العنصر أصبح ظاهرًا، وضبطنا الخاصية transform إلى none وهذا يعني أنَّ العنصر سيعود إلى حجمه الطبيعي. هذه هي النتيجة الحالية، مرر الفأرة فوق الكوكب لتشاهد مربع المعلومات. See the Pen &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;a data-cke-saved-href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io/donovanh/pen/bWezpR/&amp;amp;amp;amp;amp;amp;amp;amp;amp;#39; href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io/donovanh/pen/bWezpR/&amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;Planet hover effect part 2: basic hover effect&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;/a&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt; by Donovan Hutchinson (&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;a data-cke-saved-href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io/donovanh&amp;amp;amp;amp;amp;amp;amp;amp;amp;#39; href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io/donovanh&amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;@donovanh&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;/a&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;) on &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;a data-cke-saved-href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io&amp;amp;amp;amp;amp;amp;amp;amp;amp;#39; href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io&amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;CodePen&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;/a&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;. تطبيق تأثير الانتقال لقد أنجزنا الأمور الصعبة، وكل ما بقي علينا لنفعل هو إخبار المتصفح كيف سيتنقل بين الحالتين. ولحسن الحظ لن نحتاج إلى كتابة شيفرات طويلة، وإنما يمكن فعل ذلك بخاصية CSS وحيدة: .earth-demo * { transition: all 4s cubic-bezier(0,1.5,.3,1); } لنشرح القاعدة السابقة بالتفصيل. تُطبَّق القاعدة السابقة على كل العناصر الموجودة داخل عنصر earth-demo (وذلك باستخدام رمز النجمة *). ثم سنطبِّق تأثير الانتقال transition لجميع الخاصيات بمدة 4 ثواني وباستخدام دالة التوقيت cubic-bezier، وهذه الدالة ستبدأ بسرعة ثم تتباطأ حتى النهاية، وفي النهاية ستتخطى القيم المُحدَّدة في الحالة hover ثم ستعود إلى القيم التي ضبطناها. وقبل أن ننظر إلى النتيجة النهائية، فدعنا نضيف تأخيرًا بسيطًا إلى عناصر القائمة، فمن الجميل أن تظهر عناصر القائمة تلو بعضها بتأثيرٍ حركيٍ جميل. يمكننا فعل ذلك باستخدام الخاصية transition-delay. تأخير تأثير الانتقال سنضبط بدايةً شفافية تلك العناصر إلى الصفر، أي سيكونوا غير مرئيين قبل أن يبدأ تأثير الانتقال. .earth-demo h1, li { opacity: 0; } وعندما يبدأ الحدث hover فسنُظهرهم جميعًا: .earth-demo:hover h1, li { opacity: 0; } علينا الآن تأثير ظهور عناصر القائمة الأربعة، وذلك باستخدام المُحدِّد nth-child: .earth-demo:hover li:nth-child(1) { transition-delay: 0s; } .earth-demo:hover li:nth-child(2) { transition-delay: 0.2s; } .earth-demo:hover li:nth-child(3) { transition-delay: 0.4s; } .earth-demo:hover li:nth-child(4) { transition-delay: 0.6s; } الشيفرة السابقة ستُضيف تأخيرًا إلى كل عنصرٍ من عناصر القائمة، ولأننا استخدمنا المُحدِّد * فيما سبق فهذا يعني أنَّ كل عنصر من هذه العناصر سيُطبَّق عليه تأثير الانتقال، وكل ما علينا تحديده هو زمن التأخير. هذه هي النتيجة النهائية: See the Pen &amp;amp;amp;amp;amp;amp;amp;amp;lt;a data-cke-saved-href=&amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io/donovanh/pen/qmNgXW/&amp;amp;amp;amp;amp;amp;amp;#39; href=&amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io/donovanh/pen/qmNgXW/&amp;amp;amp;amp;amp;amp;amp;#39;&amp;amp;amp;amp;amp;amp;amp;amp;gt;Planet hover effect part 3: with transition&amp;amp;amp;amp;amp;amp;amp;amp;lt;/a&amp;amp;amp;amp;amp;amp;amp;amp;gt; by Donovan Hutchinson (&amp;amp;amp;amp;amp;amp;amp;amp;lt;a data-cke-saved-href=&amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io/donovanh&amp;amp;amp;amp;amp;amp;amp;#39; href=&amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io/donovanh&amp;amp;amp;amp;amp;amp;amp;#39;&amp;amp;amp;amp;amp;amp;amp;amp;gt;@donovanh&amp;amp;amp;amp;amp;amp;amp;amp;lt;/a&amp;amp;amp;amp;amp;amp;amp;amp;gt;) on &amp;amp;amp;amp;amp;amp;amp;amp;lt;a data-cke-saved-href=&amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io&amp;amp;amp;amp;amp;amp;amp;#39; href=&amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io&amp;amp;amp;amp;amp;amp;amp;#39;&amp;amp;amp;amp;amp;amp;amp;amp;gt;CodePen&amp;amp;amp;amp;amp;amp;amp;amp;lt;/a&amp;amp;amp;amp;amp;amp;amp;amp;gt;. لقد فعلناها! حركة معقدة نسبيًا أنجزناها باستخدام خاصية transition وحيدة. تعلمنا في هذا الدرس كيف نخطط ونبني مثالًا متكاملًا يستخدم الانتقالات لإنشاء حركات معقدة، وحرصنا أن تكون الانتقالات سلسلة وتبدو بشكلٍ جميل. الخلاصة الخدع البسيطة التي نقوم بها عبر الحركات والانتقالات هي التي تجعل موقعنا مميزًا وجميلًا ترجمة –وبتصرّف– للمقال Transitions in space لصاحبه Donovan Hutchinson
  8. كانت القدرة على التحكم بتأثيرات الانتقال Transitions والحركة Animations من إحدى الميزات التي أتت بها CSS3، وقد كان مطورو الواجهات الأمامية بحاجة كبيرة إلى مثل هذه الميزة لتصميم هذه التأثيرات باستخدام HTML و CSS فقط دون الحاجة إلى استخدام Javascript أو Flash، وقد تحققت رغبتهم أخيرًا وبعد سنوات عديدة. تتيح تأثيرات الانتقال في CSS3 تغيير مظهر أو سلوك العنصر عندما تتغير حالته، كأن يُمرَّر مؤشر الفأرة فوق العنصر hover، أو عند التركيز focus أو التنشيط active أو استهداف العنصر. أما تأثيرات الحركة في CSS3 فتتيح تغيير هيئة وسلوك العنصر من خلال مفاتيح keyframes متعددة، وهذا يعني أن تأثيرات الانتقال تقدّم تغيّرًا من حالة إلى أخرى، في حين أن تأثيرات الحركة تقدّم نقاطًا متعددة من الانتقالات من خلال مفاتيح مختلفة. تأثيرات الانتقال مثلما ذكرنا سابقًا، فإنّه ولكي يحدث تأثير الانتقال يجب أن يحدث تغير في حالة العنصر، كذلك يجب تعريف أنماط مختلفة لكل حالة من هذه الحالات. وأسهل طريقة لتحديد الأنماط لمختلف الحالات هي استخدام أشباه الأصناف التالية: :hover، :focus، :active ،:target. هناك أربعة خصائص مرتبطة بتأثيرات الانتقال وهي: transition-property، transition-duration، transition-timing-function، و transition-delay. ليست جميع هذه الخصائص مطلوبة لإنتاج تأثيرات الحركة، ولكن الخصائص الثلاثة الأولى هي الأكثر استخدامًا. في المثال التالي سيتغير لون خلفية background الصندوق خلال ثانية واحدة وبطريقة تدريجية خطّية linear. .box { background: #2db34a; transition-property: background; transition-duration: 1s; transition-timing-function: linear; } .box:hover { background: #ff7b29; } سوابق المتصفحات Vendor Prefixes لا تتضمن الشفرة السابقة كما هو الحال مع جميع الشفرات البرمجية في هذا المقال على سوابق المتصفحات، وهذا الأمر مقصود والهدف منه هو الحفاظ على الشفرة بسيطة وصغيرة الحجم وقابلة للفهم. ولتحصل على أفضل دعم في جميع المتصفحات عليك باستخدام سوابق المتصفحات. ولغرض التوضيح فقط، فإن الشفرة السابقة ستكون هكذا: .box { background: #2db34a; -webkit-transition-property: background; -moz-transition-property: background; -o-transition-property: background; transition-property: background; -webkit-transition-duration: 1s; -moz-transition-duration: 1s; -o-transition-duration: 1s; transition-duration: 1s; -webkit-transition-timing-function: linear; -moz-transition-timing-function: linear; -o-transition-timing-function: linear; transition-timing-function: linear; } .box:hover { background: #ff7b29; } خاصية الانتقال تحدّد خاصية transition-property بدقّة الخصائص التي سيتم تغييرها بالتزامن مع الخصائص الانتقالية الأخرى. تتغيّر جميع الخصائص - مبدئيًّا - ضمن الحالات المختلفة للعنصر، ولكن يمكن تحديد الخصائص المراد تغييرها ضمن قيمة transition-property وستتأثّر تلك الخصائص فقط بتأثيرات الانتقال. في المثال السابق قمنا بتعريف الخاصية background قيمةً لـ transition-property، وهذا يعني أنّها ستكون الخاصية الوحيدة التي ستخضع للتغيّر خلال ثانية واحدة وبطريقة تدريجية خطّية linear. بمعنى أنّه في حال وجود عدد من الخصائص لعنصر معيّن عند تغيّر حالته، ولكنّها غير معرّفة كقيمة لـ transition-property فإنّها لن تتلقى تأثيرات الانتقال كتلك المعرّفة في الخصائص transition-duration أو transition-timing-function. إن كنت بحاجة إلى تغيير عدد من الخصائص في الوقت نفسه، فيمكنك أن تفصلها بفواصل، كذلك يمكنك استخدام القيمة all لتطبيق تأثيرات الانتقال على جميع خصائص العنصر. .box { background: #2db34a; border-radius: 6px transition-property: background, border-radius; transition-duration: 1s; transition-timing-function: linear; } .box:hover { background: #ff7b29; border-radius: 50%; } الخصائص التي تسمح بتطبيق تأثيرات الانتقال عليها من الضروري الانتباه إلى أنّه لا تتقبّل جميع الخصائص تطبيق تأثيرات الانتقال عليها، بل فقط تلك العناصر التي تمتلك نقاطًا وسطية قابلة للتعريف. فخصائص مثل الألوان، حجم الخط وما شابهها يمكن تطبيق تأثيرات الانتقال عليها نظرًا لكونها تملك قيمًا معرّفة بين بعضها البعض. في حين أن خاصية display على سبيل المثال لا يمكنها تقبّل تأثيرات الانتقال لأنّها لا تملك أيّة قيم وسطية. القائمة التالية تبيّن مجموعة من الخصائص الشائعة التي يمكن تطبيق تأثيرات الانتقال عليها: background-color background-position border-color border-width border-spacing bottom clip color crop font-size font-weight height left letter-spacing line-height margin max-height max-width min-height min-width opacity outline-color outline-offset outline-width padding right text-indent text-shadow top vertical-align visibility width word-spacing z-index مدة تأثير الانتقال يمكن تعيين المدة التي يستغرقها تأثير الانتقال من خلال خاصية transition-duration، ويمكن استخدام وحدات توقيت عامة وهي الثانية (s) والمللي ثانية (ms)، ويمكن استخدام الأعداد العشرية في تعيين هذه القيمة، فمثلًا يمكن استخدام الصيغة التالية: .2s. عند تطبيق تأثير الانتقال على خصائص متعددة يمكن تعيين مدد متعددة أيضًا لكل خاصية، وكما هو الحال عند تعيين قيمة خاصية transition-property يمكن استخدام الفاصلة لتعيين قيم متعددة لخاصية مدة الانتقال. ولكن من الواجب الانتباه إلى أنّه عند تعيين مدد متعددة يجب مراعاة الترتيب المتّبع في تعيين الخصائص التي ستتلقّى تأثير الانتقال بواسطة خاصية transition-property، بمعنى أنّ القيمة الأولى في هذا الخاصية ستأخذ القيمة الأولى في خاصية transition-duration وهكذا دواليك. وإن طُبِّق تأثير الانتقال على خصائص متعددة مع تعيين قيمة واحدة لمدّة التأثير، فإن تلك القيمة ستطبّق على جميع الخصائص. .box { background: #2db34a; border-radius: 6px; transition-property: background, border-radius; transition-duration: .2s, 1s; transition-timing-function: linear; } .box:hover { background: #ff7b29; border-radius: 50%; } توقيت تأثير الانتقال تُستخدَم خاصّية transition-timing-function لتعيين سرعة تأثير الانتقال، ويمكن لهذا التأثير أن يمتلك سرعات مختلفة ضمن مدة زمنية واحدة وذلك بعد تعيين المدة من خلال خاصية transition-duration. وهناك قيم مفتاحية شائعة تُستخدَم مع هذه الخاصية مثل linear، ease-in، ease-out و ease-in-out. عند استخدام قيمة linear فإن الحركة تكون بسرعة ثابتة من حالة إلى أخرى، أما عند استخدام القيمة ease-in فإن الحركة تبدأ ببطء وتتسارع تدريجيًا مع مرور الوقت، وعند استخدام القيمة ease-out فإن الحركة تبدأ بسرعة وتتباطئ تدريجيًا مع مرور الوقت. أما عند استخدام القيمة ease-in-out فإن الحركة تبدأ بطيئة ثم تتسارع في الوسط لتعود إلى التباطؤ قبل الوصول إلى نهاية المدة المحددة للتأثير. تمتلك كل دالة توقيت منحنى بيزيه مكعبي Cubic-Bezier curve يمكن تعيين قيمه بدقّة بواسطة القيمة cubic-bezier(x1, y1, x2, y2) إضافة إلى قيم أخرى هي step-start و step-stop إلى جانب قيمة فريدة تحدّد من خلال steps(number_of_steps, direction). عند تطبيق تأثر الانتقال على خصائص متعددة، يمكن تعريف دوال توقيت متعددة أيضًا، وكما هو الحال مع قيم خصائص الانتقال الأخرى، يمكنك فصل القيم المتعددة بفواصل. .box { background: #2db34a; border-radius: 6px; transition-property: background, border-radius; transition-duration: .2s, 1s; transition-timing-function: linear, ease-in; } .box:hover { background: #ff7b29; border-radius: 50%; } تأخير تأثير الانتقال إضافة إلى التصريح عن كل من خاصية التأثير والمدة الزمنية ودوال التوقيت، يمكن كذلك تعيين فترة تأخير تأثير الانتقال من خلال خاصّية transition-delay، حيث تُعيَّن قيمة زمنية - بالثانية أو بالمللي ثانية - تحدد الفترة الزمنية التي تسبق انطلاق التأثير. وكما هو الحال مع جميع خصائص تأثيرات الانتقال، يمكن تأخير عدد من التأثيرات من خلال إضافة قيم متعددة مفصولة بفواصل. .box { background: #2db34a; border-radius: 6px transition-property: background, border-radius; transition-duration: .2s, 1s; transition-timing-function: linear, ease-in; transition-delay: 0s, 1s; } .box:hover { background: #ff7b29; border-radius: 50%; } الصيغة المختصرة لتأثيرات الانتقال قد يصبح التصريح عن خصائص الانتقال واحدة تلو الأخرى أمرًا مجهدًا، خصوصًا مع استخدام سوابق المتصفحات، ولحسن الحظّ يمكن اختصار العملية من خلال استخدام الخاصية transition والتي تدعم جميع الخصائص والقيم السابقة. فباستخدام قيمة transition لوحدها، يمكنك تعريف كل خصائص تأثيرات الانتقال وبالترتيب التالي: transition-property, transition-duration, transition-timing-function, وأخيرًا transition-delay. ولا حاجة لاستخدام الفواصل عند تعريف قيم هذه الخصائص إلا إذا كنت تعرّف تأثيرات انتقال متعددة. ولتعريف تأثيرات انتقال متعددة في سطر واحد، يمكنك تعيين قيم كل مجموعة من التأثيرات على حدة وفصل أي مجموعة تأثيرات إضافية باستخدام الفواصل. .box { background: #2db34a; border-radius: 6px; transition: background .2s linear, border-radius 1s ease-in 1s; } .box:hover { color: #ff7b29; border-radius: 50%; } تطبيق تأثيرات الانتقال على أيقونة HTML <button>Awesome Button</button> CSS button { border: 0; background: #0087cc; border-radius: 4px; box-shadow: 0 5px 0 #006599; color: #fff; cursor: pointer; font: inherit; margin: 0; outline: 0; padding: 12px 20px; transition: all .1s linear; } button:active { box-shadow: 0 2px 0 #006599; transform: translateY(3px); } (تجربة حية) بطاقة متقلّبة HTML <div class="card-container"> <div class="card"> <div class="side">...</div> <div class="side back">...</div> </div> </div> CSS .card-container { height: 150px; perspective: 600; position: relative; width: 150px; } .card { height: 100%; position: absolute; transform-style: preserve-3d; transition: all 1s ease-in-out; width: 100%; } .card:hover { transform: rotateY(180deg); } .card .side { backface-visibility: hidden; height: 100%; position: absolute; width: 100%; } .card .back { transform: rotateY(180deg); } (تجربة حية) تأثيرات الحركة تؤدي تأثيرات الانتقال عملًا متميّزًا من خلال إضفاء التأثيرات البصرية عند الانتقال من حالة إلى أخرى، وهي مناسبة جدًّا لمثل هذه الحالات التي يحدث فيها تغيّر الحالة لمرة واحدة فقط. ولكن عندما تكون بحاجة إلى التحكم في الأمور على نحو أدقّ فستضطر إلى إضافة المزيد من الحالات إلى تأثيرات الانتقال، وهنا يأتي دور تأثيرات الحركة. مفاتيح تأثيرات الحركة يمكن استخدام قاعدة @keyframes لتعيين النقاط التي يجب أن يحدث فيها تأثير الانتقال. تتضمن هذه القاعدة اسم تأثير الحركة، والنقاط التي تحدث فيها الحركة، والخصائص التي نرغب في تحريكها. @keyframes slide { 0% { left: 0; top: 0; } 50% { left: 244px; top: 100px; } 100% { left: 488px; top: 0; } } إضافة سوابق المتصفحات إلى قاعدة keyframe تجب إضافة سوابق المتصفحات إلى قاعدة @keyframes كما هو الحال مع خصائص تأثيرات الانتقال والحركة، وكما يلي: @-moz-keyframes @-o-keyframes @-webkit-keyframes يحمل تأثير الحركة في المثال السابق اسم slide، وقد أفصحنا عنه مباشرة بعد قاعدة @keyframes. تُعيَّن نقاط حدوث الحركة باستخدام النسبة المئوية، ابتداءً من 0% وانتهاءً بـ 100% ونقطة وسطية عند 50%. كما يمكن استخدام الكلمات المفتاحية from و to بدلًا من 0% و 100%، كما يمكن تعيين أي عدد من النقاط ضمن هذا المدى. يُصرَّح عن خصائص العنصر التي نرغب في تحريكها داخل كل نقطة، وفي المثال السابق كانت الخصائص المطلوبة هي left و top. من الضروري الانتباه إلى أنّه يمكن تحريك خاصّيّة واحدة فقط كما هو الحال مع تأثيرات الانتقال. فعلى سبيل المثال إن كنت ترغب في تحريك عنصر من الأعلى إلى الأسفل، فإن التحريك من top:0; إلى bottom: 0; لن يجدي نفعًا، لأن الحركة يمكن تطبيقها على خاصية واحدة فقط، وليس من خاصّية إلى أخرى؛ لذا من أجل تحريك العنصر من الأعلى إلى الأسفل يجب التحريك من top: 0; إلى top: 100%;. (تجربة حية). اسم تأثير الحركة بعد تعيين مفاتيح الحركة الخاصّة بتأثير الحركة، يجب إسنادها إلى أحد العناصر في الصفحة. وللقيام بذلك نستخدم خاصّية animation-name مع الاسم الذي عيّناه لقاعدة @keyframes، وتستخدم هذه الخاصّية مع العنصر الذي نرغب في تطبيق تأثيرات الحركة عليه. .stage:hover .ball { animation-name: slide; } لا يكفي استخدام خاصّية animation-name لوحدها، بل يجب تعيين قيمة لخاصية animation-duration ليعرف المتصفح المدة اللازمة لانتهاء التأثير. مدة تأثير الحركة، دالة التوقيت، وتأخير الحركة بعد أن تُعيّن قيمة خاصّية animation-name ستسلك تأثيرات الحركة نفس سلوك تأثيرات الانتقال، إذ يمكن تعيين مدّة التأثير وتعريف دالة التوقيت وتأخير التأثير حسب الرغبة. وليبدأ تأثير الحركة بالعمل فإنه بحاجة إلى تعيين مدّة التأثير من خلال خاصية animation-duration، وكما هو الحال مع تأثيرات الانتقال، يمكن لقيمة هذه الخاصّية أن تكون بالثانية أو بالمللي ثانية. .stage:hover .ball { animation-name: slide; animation-duration: 2s; } يمكن تعريف دالّة التوقيت وتأخير تأثّر الحركة باستخدام الخاصّيتين animation-timing-function و animation-delay على التوالي، ولا يوجد أي فرق في القيم التي تستقبلها هاتان الخاصيتان أو طريقة عملها بين تأثيرات الانتقال وتأثيرات الحركة. .stage:hover .ball { animation-name: slide; animation-duration: 2s; animation-timing-function: ease-in-out; animation-delay: .5s; } في المثال التالي سترتدّ الكرة (العنصر<figure> مع النمط ball) أثناء تحرّكها إلى جهة اليسار، ويمكن مشاهدة الحركة من خلال تمرير مؤشر الفأرة فوق العنصر <div> ذي النمط stage. HTML <div class="stage"> <figure class="ball"></figure> </div> CSS 0% { left: 0; top: 0; } 50% { left: 244px; top: 100px; } 100% { left: 488px; top: 0; } } .stage { height: 150px; position: relative; } .ball { height: 50px; position: absolute; width: 50px; } .stage:hover .ball { animation-name: slide; animation-duration: 2s; animation-timing-function: ease-in-out; animation-delay: .5s; } (تجربة حية) تخصيص تأثيرات الحركة تتيح تأثيرات الحركة المزيد من التخصيص لسلوك العنصر، فيمكن تعيين عدد مرات تكرار الحركة والاتجاه الذي ستنتهي فيه الحركة. تكرار تأثير الحركة لا يتكرر تأثير الحركة بصورة افتراضية بل يتوقف بعد إتمام الدورة الأولى، ولجعل التأثير يتكرّر مرات متعددة يمكن استخدام خاصّية animation-iteration-count، وتتضمن قيم هذه الخاصية إمّا أعداد صحيحة أو كلمة infinite المفتاحية. في الحالة الأولى سيتكرر تأثير الحركة بحسب العدد المحدّد، أما في الحالة الثانية فإن تأثير الحركة سيتكرّر إلى ما لا نهاية. .stage:hover .ball { animation-name: slide; animation-duration: 2s; animation-timing-function: ease-in-out; animation-delay: .5s; animation-iteration-count: infinite; } (تجربة حية) اتجاه تأثير الحركة وإلى جانب القدرة على تعيين عدد مرات تكرار تأثير الحركة، يمكن كذلك تعيين اتجاه انتهاء التأثير باستخدام الخاصية animation-direction، وتأخذ هذه الخاصية القيم: normal، reverse، alternate و alternate-reverse. استخدام القيمة normal يعني أن الحركة ستسير بشكل طبيعي من البداية إلى النهاية، أما القيمة reverse فتعني أن الحركة ستسير بعكس الطريقة المصرّح عنها في قاعدة @keyframes، أي ستبدأ الحركة من 100% وتنتهي بـ 0%. عند استخدام القيمة alternate فإن الحركة ستسير جيئة وذهابًا، أي ستبدأ الحركة من 0% لتتّجه إلى 100% ثم تعود من هذه القيمة إلى 0% مرة أخرى. يمكن تحديد عدد مرّات تكرار الحركة بالاتجاه الأمامي والخلفي وذلك باستخدام الخاصّية animation-iteration-count، حيث يبدأ العدّ من الرقم 1 فتبدأ الحركة من القيمة 0% وصولًا إلا 100% وتكتمل الدورة الأولى، بعد ذلك نعود من القيمة 100% إلى 0% فتضاف دورة أخرى إلى العدّاد، وبهذا نحصل على دورتين بالمجمل. تعمل القيمة alternate كذلك على قلب دوال التوقيت عند بدء الحركة بشكل عكسي، فإن كان تأثير الحركة يستخدم القيمة ease-in عند التحرك من 0% إلى 100% فإنّه سيستخدم القيمة ease-out عند الانتقال من 100% إلى 0%. أخيرًا، تدمج القيمة alternate-reverse القيمتين alternate و reverse، وتكون الحركة بالاتجاه الخلفي ثم بالاتجاه الأمامي، أي تبدأ الحركة من 100% باتجاه 0% لتعود مرّة أخرى إلى 100%. .stage:hover .ball { animation-name: slide; animation-duration: 2s; animation-timing-function: ease-in-out; animation-delay: .5s; animation-iteration-count: infinite; animation-direction: alternate; } (تجربة حية) حالة تأثير الحركة تسمح خاصّية animation-play-state بتشغيل تأثير الحركة أو إيقافه مؤقتًا باستخدام خيارين هما running و paused على التوالي. عند إعادة تشغيل تأثير الحركة المتوقف مؤقتًا فإنّ التأثير يعود إلى الحركة من النقطة التي توقّف عندها وليس من نقطة البداية. في المثال التالي تم تعيين قيمة paused للخاصّية animation-play-state وذلك عند النقر على العنصر ذي النمط stage. لاحظ كيف أن الحركة ستبقى متوقّفة بصورة مؤقتة إلى حين إفلات زر الفأرة. .stage:hover .ball { animation-name: slide; animation-duration: 2s; animation-timing-function: ease-in-out; animation-delay: .5s; animation-iteration-count: infinite; animation-direction: alternate; } .stage:active .ball { animation-play-state: paused; } (تجربة حية) نمط التعبئة الخاصّ بتأثير الحركة تعرّف الخاصّية animation-fill-mode النمط الذي سيطبّق على العنصر قبل أو بعد أو قبل وبعد عمل تأثير الحركة، ولهذه الخاصّية أربع قيم هي: none, forwards, backwards, و both. عند استخدام القيمة none لن يتم تطبيق أي نمط على العنصر قبل أو بعد تطبيق تأثير الحركة. القيمة forwards ستحافظ على الأنماط المعرّفة في المفتاح الحركي الأخير، ولكن يجب الانتباه إلى أن هذه الأنماط قد تتأثّر بقيم الخاصّيتين animation-direction و animation-iteration-count فتتغيّر نقطة انتهاء تأثير الحركة. القيمة backwards ستطبّق الأنماط الموجودة في المفتاح الحركي الأول بمجرد أن يتم تعريفها، وقبل انطلاق تأثير الحركة، وهذا يتضمن تطبيق تلك الأنماط خلال مدة التأخير المحدّدة لتأثير الحركة. إلى جانب ذلك، فإنّ القيمة backwards قد تتأثّر بقيمة الخاصّية animation-direction. وأخيرًا، فإنّ القيمة both تجمع في عملها بين عمل القيمتين السابقتين. .stage:hover .ball { animation-name: slide; animation-duration: 2s; animation-timing-function: ease-in-out; animation-delay: .5s; animation-fill-mode: forwards; } .stage:active .ball { animation-play-state: paused; } (تجربة حية) صيغة مختصرة لتأثيرات الحركة كما هو الحال مع تأثيرات الانتقال، هناك صيغة مختصرة لتعريف تأثيرات الحركة، ويتم ذلك من خلال استخدام الخاصية animation بدلًا من تعريف القيم واحدة تلو الأخرى. وتأخذ القيم التابعة لهذه الخاصية الترتيب التالي: animation-name, animation-duration, animation-timing-function, animation-delay, animation-iteration-count, animation-direction, animation-fill-mode, وأخيرًا animation-play-state. .stage:hover .ball { animation: slide 2s ease-in-out .5s infinite alternate; } .stage:active .ball { animation-play-state: paused; } (تجربة حية) ترجمة - وبتصرّف - للمقال Transitions & Animations لصاحبه Shay Howe.
  9. سنستعمل في هذا الدرس تحريكات CSS بسيطة إضافةً إلى بعض شفرات JavaScript لإنشاء ساعة متحركة. سنُنشِئ هذه الساعة باستخدام HTML و CSS وخلفية SVG إضافةً إلى بعض أسطر JavaScript. سنستعمل التحريكات Animations أو الانتقالات Transitions في CSS، وسنعتمد على JavaScript لضبط التوقيت الابتدائي. ملحوظة: يتضمّن الملف المرفق شفرة الأمثلة المذكورة في هذا الدرس. شفرات HTML سنبدأ بإضافة بعض شفرات HTML. فكَّرتُ بداية الأمر باستخدام ثلاثة عناصر لكل عقرب من عقارب الساعة، ومن ثم وضعتُ تلك العناصر ضمن حاوية؛ وصحيحٌ أننا نستطيع استخدام العناصر الثلاثة بمفردها مع تحريكات CSS لكننا سنحتاج إلى الحاويات (Containers) لوضع العقارب في مكانها المناسب وتحريكها. <article class="clock"> <div class="hours-container"> <div class="hours"></div> </div> <div class="minutes-container"> <div class="minutes"></div> </div> <div class="seconds-container"> <div class="seconds"></div> </div> </article> لن نستخدم الشفرة أعلاه الآن، لكننا سنكتبها خطوة خطوة. بالنسبة للتنسيقات فسنعتمد على ملف التنسيقات assets/clocks.css في المرفق مع شرح العناصر الأساسية فيه. إن أردتَ رؤية النتيجة التي نريد الوصول إليها بنهاية الدرس فتمكنك معاينة المستند examples/1.html الموجود في الملف المرفق. واجهة الساعة نستخدم الشفرة التالية في ملف التنسيقات لإعطاء الساعة شكلها الدائري. .clock { border-radius: 50%; background: #fff url(ios_clock.svg) no-repeat center; background-size: 88%; height: 20em; padding-bottom: 31%; position: relative; width: 20em; } .clock.simple:after { background: #000; border-radius: 50%; content: ""; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); width: 5%; height: 5%; z-index: 10; } أضفنا أيضًا دائرةً سوادء اللون في المنتصف وجعلناها «أعلى» من غيرها (عبر خاصية z-index) لكي تقع عقارب الساعة خلفها. نضع المحتوى التالي في ملف HTML: <link rel="stylesheet" href="assets/clocks.css"> <div class="demo-container clocks single"> <article class="clock simple show"></article> </div> إن فتحت الملف الناتج عن هذه الخطوة (examples\2.html) في المتصفح، والذي يحوي شفرة HTML التي تحصلنا عليها لحدّ الساعة، فستجد أنه يرسم شكل الساعة ولكن من دون عقارب. تضبط الشفرة التاليّة في ملف CSS موضع الحاويات قبل إضافة العقارب: .minutes-container, .hours-container, .seconds-container { position: absolute; top: 0; right: 0; bottom: 0; left: 0; } عقرب الساعات نضيف الحاويّة الخاصّة بعقرب الساعات، والعنصر الخاص بالعقرب نفسه إلى ملف HTML: <link rel="stylesheet" href="assets/clocks.css"> <div class="demo-container clocks single"> <article class="clock simple show"> <div class="hours-container"> <div class="hours"></div> </div> </article> </div> نحصُل على الملف examples/3.html. إن نظرت في ملف تنسيقات CSS فستجد أننا نستعمل القيمة absolute للخاصية position لجعل مكان العقرب مطلقًا. .hours { background: #000; height: 20%; left: 48.75%; position: absolute; top: 30%; transform-origin: 50% 100%; width: 2.5%; } كما أننا استخدمنا النسب المئوية لتسهيل إعادة تحجيم الساعات، مما يجعل من السهل ملء الشاشة بالساعة أو إظهارها على شاشات الهواتف المحمولة. ضبطنا أيضًا قيمة الخاصية transform-origin إلى أسفل العقرب لتمكين تدويره لاحقًا. عقرب الدقائق وهو يشبه عقرب الساعات، لكنه أطول وأضيق. نضيفه أولا إلى ملف HTML: <link rel="stylesheet" href="assets/clocks.css"> <div class="demo-container clocks single"> <article class="clock simple show"> <div class="hours-container"> <div class="hours angled"></div> </div> <div class="minutes-container" style="transform: rotateZ(6deg);"> <div class="minutes"></div> </div> </article> </div> نحصُل على المستند examples/4.html. يُنسَّق الصنف في CSS على النحو التالي: .minutes { background: #000; height: 40%; left: 49%; position: absolute; top: 10%; transform-origin: 50% 100%; width: 2%; } عقرب الثواني أما عقرب الثواني، فهو أكثر ضيقًا من سابقه، لكنه يمتد إلى ما بعد منتصف الساعة. نضيف عنصر العقرب ضمن حاويتّه فنحصُل على examples/5.html: <link rel="stylesheet" href="assets/clocks.css"> <div class="demo-container clocks single"> <article class="clock simple show"> <div class="hours-container"> <div class="hours angled"></div> </div> <div class="minutes-container" style="transform: rotateZ(6deg);"> <div class="minutes angled"></div> </div> <div class="seconds-container"> <div class="seconds"></div> </div> </article> </div> لتنسيق طول عقرب الثواني وضيقه ضبطنا قيمة الخاصية transform-origin إلى 80%، مما يبقي 20% من العقرب ممتدةً بعيدًا عن المنتصف. .seconds { background: #000; height: 45%; left: 49.5%; position: absolute; top: 14%; transform-origin: 50% 80%; width: 1%; z-index: 8; } لدينا الآن ساعة دائرية بالعقارب المطلوبة: الساعات، الدقائق والثواني؛ إلا أنّ هذه العقارب ثابتة ولا تتحرك كما يجدر بها أن تفعل. سنضبُط هذا الأمر في الفقرات التالية. الحركة تنتقل عقارب بعض أنواع الساعات كل ثانية محدثةً صوتًا، وأخرى تتحرك عقاربها بسلاسة. لنفعل كلا الأمرين ولنبدأ بتحريك العقارب بسلاسة أولًا. استخدمنا في كلتا الحالتين التعليمة keyframes لتحريك العقارب 360 درجة: @keyframes rotate { 100% { transform: rotateZ(360deg); } } عقرب الساعات يتحرك بخطوات متصلة ستطلب الشِفرة السابقة من العنصر أن يدور 360 درجة إذا استخدمنا الخاصية animation في صنف CSS المطبّق على عنصر HTML. يتيح استخدام دالة الزمن linear أن تكون الحركة خطيّةً وسلسةً: .hours-container { animation: rotate 43200s infinite linear; } .minutes-container { animation: rotate 3600s infinite linear; } .seconds-container { animation: rotate 60s infinite linear; } سندوِّر عقرب الساعات hours مرةً كل 12 ساعة (أي 43200 ثانية)، وسيدور عقرب الدقائق دورةً كاملةً كل ساعة (3600 ثانية)، أما عقرب الثواني فيكمل دورته كل دقيقة (60 ثانية). ينتُج لدينا مستند examples/6.htmlوالذي يحوي شفرة HTML التالية: <link rel="stylesheet" href="assets/clocks.css"> <div class="demo-container clocks single linear"> <article class="clock simple show"> <div class="hours-container"> <div class="hours angled"></div> </div> <div class="minutes-container" style="transform: rotateZ(6deg);"> <div class="minutes angled"></div> </div> <div class="seconds-container"> <div class="seconds"></div> </div> </article> </div> إذا كنتَ ذا بصرٍ ثاقب، فستلاحظ حركة عقرب الدقائق البطيئة جدا؛ حيث سيحتاج إلى ساعةٍ كاملةٍ لإكمال دورانه؛ أما عقرب الثواني فسيحتاج إلى 60 ثانية فقط مما يُسهِّل ملاحظته. عقرب الثواني يتحرك بخطوات منفصلة يمكننا جعل حركة العقارب كما في الساعات التقليدية بتحريك عقرب الثواني 60 حركة منفصلة في الدقيقة. إحدى أبسط الطرائق لفعل ذلك هي استخدام دالة التوقيت steps، أي ستصبح الخاصية animation كما يلي: .minutes-container { animation: rotate 3600s infinite steps(60); } .seconds-container { animation: rotate 60s infinite steps(60); } ونعدّل ملف HTML لنحصُل على مستند examples/7.html ذي المحتوى التالي (لاحظ استخدام الصنف steps مكان الصنف linear): <link rel="stylesheet" href="assets/clocks.css"> <div class="demo-container clocks single steps"> <article class="clock simple show"> <div class="hours-container"> <div class="hours angled"></div> </div> <div class="minutes-container" style="transform: rotateZ(6deg);"> <div class="minutes angled"></div> </div> <div class="seconds-container"> <div class="seconds"></div> </div> </article> </div> أصبح عقربا الساعة يتحركان 60 حركة منفصلة لإتمام الدورة، وسيحسب المتصفح تلقائيًا ما هي المسافة المقطوعة في كل خطوة. إظهار الوقت الصحيح صحيحٌ أنَّ الساعات السابقة جميلة، لكنها لا تعرض الوقت الحالي. يمكننا عرض الوقت الصحيح باستخدام بعض شِفرات JavaScript: /* * البدء بالوقت المضبوط في جهاز المستخدم * From: cssanimation.rocks/clocks */ function initLocalClocks() { // Get the local time using JS var date = new Date; var seconds = date.getSeconds(); var minutes = date.getMinutes(); var hours = date.getHours(); // إنشاء كائن لعقارب الساعة لثلاثة: الساعات، الدقائق والثواني var hands = [ { hand: 'hours', angle: (hours * 30) + (minutes / 2) }, { hand: 'minutes', angle: (minutes * 6) }, { hand: 'seconds', angle: (seconds * 6) } ]; // ضبط زوايا العقارب for (var j = 0; j < hands.length; j++) { var elements = document.querySelectorAll('.' + hands[j].hand); for (var k = 0; k < elements.length; k++) { elements[k].style.webkitTransform = 'rotateZ('+ hands[j].angle +'deg)'; elements[k].style.transform = 'rotateZ('+ hands[j].angle +'deg)'; // إذا تعلق الأمر بعقرب الدقائق فإننا نحفظ الثواني لحساب موضع عقرب الدقائق في ما بعد if (hands[j].hand === 'minutes') { elements[k].parentNode.setAttribute('data-second-angle', hands[j + 1].angle); } } } } هذه الدالة تحوِّل الوقت الحالي (الساعات والدقائق والثواني) إلى الزاوية الموافقة له لكل عقربٍ من عقارب الساعة، ومن ثم ستُطبِّق الزاوية الصحيحة لكل عقرب على حدة باستخدام القيمة rotateZ على الخاصية style.transform. نضيف إلى مستند HTML قيما مبدئيّة للخاصيّتين style.transform وdata-second-angle (التي تحفظ الثواني لحساب موضع عقرب الدقائق). بدون هذه القيم لن تجد شفرة جافاسكربت السابقة العناصر لتنفيذ التعليمات عليها. نحصُل في ختام هذه الخطوة على المستند examples/8.html (الذي يستدعي ملف جافاسكريبت clocks.js حيث توجد دوال جافاسكربت السابقة). سيعمل ما سبق في أغلبية المتصفحات دون مشاكل، عدا متصفح Safari الذي علينا استعمال سابقة (prefix) خاصة معه، ولهذا السبب سنستعمل الخاصية style.webkitTrasform أيضًا. مزامنة حركة عقرب الثواني والدقائق علينا الحرص على تحريك عقرب الدقائق عندما يبلغ عقرب الثواني الساعة الثانية عشرة، كما في الصورة المتحركة الآتية. عندما تُرسَم الساعة على الشاشة لأوّل مرة، فيجب تحريك عقرب الدقائق بعد أقل من دقيقة واحدة، ولفعل ذلك علينا حساب متى ستنتهي أوّل دقيقة ومن ثم تحريك العقرب يدويًا. ولمّا كنّا نستعمل JavaScript لضبط الحركة الأوليّة، فسنستمر باستخدامها عبر تحريك العقرب بمقدار ست درجات كل دقيقة باستخدام الدالة setInterval. وقبل تحريك عقرب الدقائق، علينا حساب كم تبقى من الدقيقة الحالية. ربما لاحظتَ هذه الأسطر في الشِفرة السابقة: if (hands[j].hand === 'minutes') { elements[k].parentNode.setAttribute('data-second-angle', hands[j + 1].angle); } الأسطر السابقة تختبر إن كان العقرب هو عقرب الدقائق، وإذا تحقق ذلك فسنضبط خاصيةً باسم data-second-angle تحتوي على الزاوية الحالية لعقرب الثواني. يمكننا الاستفادة من هذه المعلومات لتحريك عقرب الدقائق. /* ضبط المدة المتبقية من الدقيقة عند ظهور الساعة لأول مرة، ثم تحريك العقرب كل دقيقة بعد انتهاء الدقيقة التي ظهرت فيها الساعة على الصفحة. */ function setUpMinuteHands() { // إيجاد القدر المتبقي من الدقيقة عند ظهور الساعة var containers = document.querySelectorAll('.minutes-container'); var secondAngle = containers[0].getAttribute("data-second-angle"); if (secondAngle > 0) { // ضبط عدّاد ينتهي مع الدقيقة الحالية من أجر تحريك عقرب الدقائق var delay = (((360 - secondAngle) / 6) + 0.1) * 1000; setTimeout(function() { moveMinuteHands(containers); }, delay); } } /* * تدوير العقرب بالنسبة للدقيقة الأولى */ function moveMinuteHands(containers) { for (var i = 0; i < containers.length; i++) { containers[i].style.webkitTransform = 'rotateZ(6deg)'; containers[i].style.transform = 'rotateZ(6deg)'; } // الاستمرار بعد الدقيقة الأولى في تدوير عقرب الدقائق كل 60 ثانية setInterval(function() { for (var i = 0; i < containers.length; i++) { if (containers[i].angle === undefined) { containers[i].angle = 12; } else { containers[i].angle += 6; } containers[i].style.webkitTransform = 'rotateZ('+ containers[i].angle +'deg)'; containers[i].style.transform = 'rotateZ('+ containers[i].angle +'deg)'; } }, 60000); } إضافة ارتداد للعقارب علينا حذف خاصية الحركة في CSS لاستخدامنا JavaScript لضبط مختلف جوانب الحركة؛ لكن بدلًا من حذفها فقط، سنضع بدلًا منها انتقالًا (transition)؛ وهذه فرصةٌ ملائمةٌ لإضافة خصائص أخرى للحركة. عندما نضبط زاويةً جديدةً في JavaScript للعقرب، فسيُطبّق انتقالٌ (transition) في CSS الذي سيخبر المتصفح عن الحركة، وهذا يعني أنَّ شِفرة JavaScript ستتعامل مع تغيرات بسيطة في الزاوية وسيتكفّل المتصفح بعملية التحريك. قبل فعل ذلك، علينا تحديث الشِفرة لاستخدام JavaScript لتحريك عقرب الثواني أيضًا، حيث سنستخدم الشِفرة الآتية لتحريك حاوية عقرب الثواني ستين مرة في الدقيقة: /* * تحريك حاويات الثواني */ function moveSecondHands() { var containers = document.querySelectorAll('.seconds-container'); setInterval(function() { for (var i = 0; i < containers.length; i++) { if (containers[i].angle === undefined) { containers[i].angle = 6; } else { containers[i].angle += 6; } containers[i].style.webkitTransform = 'rotateZ('+ containers[i].angle +'deg)'; containers[i].style.transform = 'rotateZ('+ containers[i].angle +'deg)'; } }, 1000); } بعد أن أصبحت حركة عقارب الثواني والدقائق مدارةً من JavaScript، فعلينا تحديث شِفرة CSS لنستبدل الخاصية transitions بالخاصية animation: .minutes-container { transition: transform 0.3s cubic-bezier(.4,2.08,.55,.44); } .seconds-container { transition: transform 0.2s cubic-bezier(.4,2.08,.55,.44); } هذه الانتقال الذي طبّقناه على خاصية transform يستعمل دالة التوقيت cubic-bezier، وهذه الدالة ستعطي العقرب حركةً ارتداديةً إلى الخلف قبل الدوران باتجاه عقارب الساعة. يمكنك تجربة التأثيرات المضافة في هذه الفقرة بمعاينة الملف examples/9.html. محاكاة الساعة الموجودة في نظام iOS 7 أنا أحد معجبي بساطة الساعة المستعملة في نظام iOS 7؛ وبإعادة تنسيق العقارب وبإضافة صورة خلفية مع الأرقام، فسنتمكن بسهولة من إنشاء مثل هذه الساعة، كما في المثال examples/10.html. هذا التصميم مبنيٌ على تصميم ساعة Swiss railway clock الشهيرة، يمكننا تعديل ساعتنا لتشبهها عبر تغيير الأنماط المستعملة واستعمال صورة خلفية جديدة، كما في المثال examples/11.html. توافق المتصفح يمكن للمتصفحات الحديثة التعامل مع الانتقالات والحركات في CSS بما في ذلك متصفح IE 10+‎، والإصدارات الحديثة من متصفحَي Chrome و Firefox اللذين يدعمانهما دون سابقة (prefix)، أما Safari فعلينا استعمال السابقة ‎-webkit معه. رأينا في هذا الدرس كيفية إنشاء ساعة والتحكم في عقاربها باستخدام تأثيرات CSS وتنفيذ تعليمات جافاسكريبت. يمكنك الاستفادة من الأمثلة المذكورة في الدرس لإنشاء ساعات مخصّصة لأغراضك. إن كنت تفكّر ساعات بمناطق زمنيّة مختلفة مثل تلك التي نراها في الفنادق فيمكنك الاستعانة بمكتبتي Moment.js وMoment.js Timezone. ترجمة –وبتصرّف– للمقال Clocks لصاحبه Donovan Hutchinson. حقوق الصورة البارزة محفوظة لـ Freepik
  10. تُقدّم أشباه العناصر (pseudo-elements) عناصر DOM إضافيّة وبدون عناء يُذكر، فهي تَسمح للمُطوّر في إضافة مُحتوى إضافي إلى الصفحات وبدون إضافة أيًا من عناصر HTML على الصفحة، كما يُمكن لها أنّ تتحرّك (animated). ستتناول هذه المقالة استخدام شبه عنصر (pseudo-element) لإضافة تأثير بصري على زر. Shiny effect شبه العناصر Pseudo-elements يُمكن باستخدام CSS تحديد شبه عنصر باستخدام ::before أو ::after ليتم بعد ذلك إدراج شبه العنصر ضمن العنصر، أو بين العنصر و محتوى ما، وباعتبار أنّ شبه العنصر يعمل عمل أي عنصر، فمن المُمكن أنّ يتمّ تنسيقه، أو توضيعه، وستكون صياغة الشيفرة الخاصّة به على الشكل التّالي: .pebble::before { ... } .pebble::after { ... } يُمكن القول هنا، أنّ العنصر pebble. يملك عنصرين وهميين مُرتبطين به، ويُمكن تنسيقهما أيضًا. ملاحظة حول الفرق بين استخدام "::" و ":" يُقبَل عامًّا استخدام تضعيف النقطتان، وذلك للدلالة على استخدام شبه العناصر، وذلك على عكس شبه الأصناف (pseudo-classes) مثل :hover أو :first-child، ولكن يجب استخدام ( في حال الرغبة في دعم IE8، مع العلم أنّ جميع المُتصفّحات الأخرى وبإصداراتها الأخيرة تدعم النقطتان المُضاعفتان (::). استخدام خاصية content يجب عند استخدام شبه العناصر، ضبط الخاصّيّة content لكي يُصبح شبه العناصر مرئيًا على الصّفحة، ومن المُمكن الاحتيال عليه للظهور عبر استخدام مُحتوى فارغ كما في التّالي: .pebble::before { content: "" ... more styling goes here... } .shiny{-webkit-perspective:500px;perspective:500px;-webkit-transform-style:preserve-3d;transform-style:preserve-3d;display:inline-block}.shiny button{background:#d1703c;color:#fff;font-size:14px;border:none;border-radius:0.5em;height:3em;padding:0 1em;position:relative;overflow:hidden;line-height:2em;-webkit-transition:all 0.5s cubic-bezier(.67,-0.51,.42,1.43);transition:all 0.5s cubic-bezier(.67,-0.51,.42,1.43)}.shiny button:hover,.shiny button:focus{border-color:#d1703c;color:#fff;font-size:24px}.shiny button:hover::after,.shiny button:focus::after,.shiny .demo-container.active button::after{-webkit-animation:sheen 1s 0.5s forwards;animation:sheen 1s 0.5s forwards}.shiny button::after{content:'';position:absolute;top:-50%;right:-50%;bottom:-50%;left:-50%;background:-webkit-linear-gradient(top,rgba(209,112,60,0),rgba(255,255,255,0.5) 50%,rgba(209,112,60,0));background:linear-gradient(to bottom,rgba(209,112,60,0),rgba(255,255,255,0.5) 50%,rgba(209,112,60,0));-webkit-transform:rotateZ(60deg) translate(-5em,7.5em);transform:rotateZ(60deg) translate(-5em,7.5em)}.shiny button.visible{overflow:visible}.shiny button:hover{cursor:pointer}@-webkit-keyframes sheen{100%{-webkit-transform:rotateZ(60deg) translate(1em,-14em);transform:rotateZ(60deg) translate(1em,-14em)}}@keyframes sheen{100%{-webkit-transform:rotateZ(60deg) translate(1em,-14em);transform:rotateZ(60deg) translate(1em,-14em)}} يجب أنّ تجعل الشيفرة السابقة من العنصر مرئيًا على الصّفحة. الزر البراق (Shiny button) سيتمّ استخدام شبه العنصر لإتمام هذا المثال، وذلك عبر إنشاء تأثير اللّمعان عند المرور فوق الزر، كما في المثال. Shiny effect البداية مع شيفرة HTML <button>Oooh SHINY</button> لا يوجد حاجة إلى كتابة المزيد من سطور HTML للمُتابعة، على اعتبار أنّه سيتمّ استخدام شبه العنصر لإضافة بقيّة المُحتوى، ولكن لا بأس من إضافة صنف (class) إلى الوسم <button> لتنسيقه عند وجود أكثر من نوع على الصّفحة، ولكن للمثال الحالي سيتمّ استخدام عنصر الزر على حاله للتبسيط. إضافة التأثير إن التأثير المُراد إضافته ما هو إلا تدرّج خطي (linear gradient) يمر عبر الزر، ولإنشاء هذا التدرّج سيتمّ استخدام شبه العنصر after، وتوضيعه في خارج الزر وفي بدايته. button::after { content: ''; position: absolute; top: -50%; right: -50%; bottom: -50%; left: -50%; background: linear-gradient(to bottom, rgba(229, 172, 142, 0), rgba(255,255,255,0.5) 50%, rgba(229, 172, 142, 0)); transform: rotateZ(60deg) translate(-5em, 7.5em); } يُصنع تأثير اللّمعان من تدرّج اللون الخارجي للزر إلى الأبيض ومن ثُمّ إلى العودة إلى اللون الأصلي. يجب إخفاء طبقة اللّمعان لتظهر فقط عند حركة المرور (hover)، ولعمل ذلك سيتمّ ضبط خاصّيّة overflow إلى hidden للزر، وباعتبار أنّ شبه العنصر هو ضمن الزر، فهذا يعني أنّ تموضعه خارج الزر لن يكون مرئيًّا. button { background: #e5ac8e; color: #fff; font-size: 14px; border-radius: 0.5em; padding: 0 1em; position: relative; overflow: hidden; line-height: 32px; } تمّ إضافة بعض التنسيق إلى الزر لكي يظهر بارزًا وذو منظرٍ خاصٍّ به، تجدر الإشارة هنا إلى استخدام position: relative، وذلك لكي يكون شبه العنصر المتموضع بشكل مُطلق (absolutely) مُتواجدًا داخل الزر، فبدون ضبط هذه الخاصّيّة، سيتموضع العنصر ذو التَمَوْضُع المُطلق ضمن العنصر الأب. إضافة التحريك (Adding the animation) يجب لاستكمال هذا المثال باستخدام التحريك: أوّلًا: إخبار المُتصفّح ليستخدم التحريك عند حركة المرور (hover). ثانيًا: تحديد بالضَّبط ما هو التحريك المطلوب وذلك باستخدام keyframes. يتمّ إضافة حالة المرور عبر إلحاق after إلى hover كما في التّالي: button:hover::after, button:focus::after { animation: sheen 1s forwards; } تمّ في الشيفرة السابقة إخبار المُتصفّح، أنّه عند حركة المرور (hover)، يجب على شبه العنصر after أنّ يُطبّق التحريك animation، ذو الاسم “sheen”، ولمدّة ثانية واحدة، ويتوقف عند النهاية بدون تكرار. يجب الأخذ بعني الاعتبار الترتيب، فاستخدام ::after:hover لن يعمل، حيثُ عندها سيتمّ إخبار المُتصفّح ليتفاعل مع حالة المرور (hover) لشبه العنصر نفسه. تتوفّر الشيفرة السابقة أيضًا على حالة التمركز (focus)، والّتي تعني أنّ المُستخدم الّذي يضغط على زر لوحة المفاتيح tab ضمن الصّفحة سيرى التأثير "sheen" أيضًا عند الوصول إليه، وبدون الحاجة لحركة المرور. سيتمّ في الخطوة التّالية تعيين وضبط keyframes لهذا التحريك: @keyframes sheen { 100% { transform: rotateZ(60deg) translate(1em, -9em); } } تمّ في الشيفرة السابقة كتابة keyframe واحد فقط، وذلك باعتبار أنّ بداية التَمَوْضُع (0%) هي مُضمّنة من قبل تَمَوْضُع بداية شبه العنصر، فكل ما يجب فعله هو ضبط نهاية التَمَوْضُع، والتي ستكون أعلى يمين الزر، ليُحاكي المُتصفح هذا التأثير Shiny effect دعم المتصفحات للتحريك أصبحت الخاصّيّة animation، و شبه العناصر مدعومة بشكل جيّد مع آخر إصدارات المُتصفّحات، ولكن يُستحسن دائمًا إلحاق السوابق webkit و moz من أجل الخاصّيّة keyframes. ترجمة وبتصرف للمقال Animating pseudo-elements.
  11. في درس سابق تعرفنا على كيفية تطبيق انتقالات Transitions على الشرائح، وهي تأثيرات حركية تُشغّل عند الانتقال من شريحة إلى أخرى. في هذا الدرس سنتعرف على كيفية تطبيق حركات Animations على العناصر داخل الشريحة، كالنصوص، الصور، الأشكال، المخططات، الرسومات، وغيرها. من السهل جدا تطبيق الحركات في باوربوينت، وهي من الخصائص الرائعة التي تضيف عامل جذب بصري لعروضك التقديمية يزيد من اهتمام المشاهد. الشريحة أعلاه هي مثال على حركات مختلفة مطبقة على عدد من العناصر. قمنا بتطبيق حركة Bounce على مربع العنوان، حركة Grow & Turn على النصوص، حركة Float In على المخطط، وحركة Wipe على الصورة. وكل حركة من هذه الحركات تمتلك خيارات بديلة للتأثير. لإضافة حركة لأي عنصر من العناصر قم بتحديده أولا، ثم اذهب إلى تبويب حركات Animations، واختر الحركة المرغوبة من معرض الحركات: عند النقر على الحركة ستُعرض معاينة لها بشكل تلقائي، يمكنك إيقاف المعاينة التلقائية AutoPreview بإلغاء تأشيرها من زر معاينة Preview، واستخدام هذا الزر لعرض المعاينة يدويا: عند اختيار الحركة، يمكنك عرض خيارات التأثير لها من زر خيارات التأثير Effect Options. وتختلف هذه التأثيرات للحركة الواحدة باختلاف العنصر. فإذا قمت بتطبيق حركة Fade على النصوص ستختلف خيارات التأثير فيما لو قمت بتطبيقها على مخطط. مثلا، من خيارات التأثير لحركة Float In التي قمنا بتطبيقها على المخطط يمكننا تغيير اتجاه Direction حركة سلاسل المخطط لتكون من الأعلى إلى الأسفل، أو تغيير تتابع Sequence ظهور عناصر المخطط حسب الفئة By Category أو حسب العناصر في السلسلة By Elements in Series: ولإلغاء الحركة من العنصر، قم بتحديده ثم اختر الحركة بلا None من معرض الحركات: تحريك النصوصتوجد في باوربوينت أربعة مجاميع مختلفة من الحركات: حركات الدخول Entrance: تأثيرات جلب العناصر إلى داخل الشريحة أو إظهارها في العرض.حركات التوكيد Emphasis: تستخدم لإضافة تأثير حركي على العناصر في الشريحة وليس جلبها إلى داخل الشريحة أو إخراجها.حركات الخروج Exit: تأثيرات إخراج العناصر من الشريحة أو جعلها تختفي من العرض.مسار الحركة Motion Paths: لتحريك العناصر بمسار معين داخل الشريحة.يمكنك اختيار أي نوع من هذه المجاميع وتطبيقها على النصوص، لكن من الأفضل ألّا يكون الاختيار عشوائيا. يمكنك مثلا أن تطبق حركات الدخول على العناوين الرئيسية، وحركات التوكيد على بقية النصوص. ليست هناك قواعد لاختيار الحركات، المهم أن تكون النتيجة النهائية لتطبيقها ذات وقع بصري جذاب. كما ذكرنا أعلاه، لتطبيق حركة على النصوص قم بتحديدها أولا ثم اختر حركة من معرض الحركات. سنقوم مثلا بتطبيق حركة Appear على العنوان في الشريحة التالية: ستلاحظ ظهور أرقام بجانب العناصر عند تطبيق الحركة. هذه الأرقام تشير إلى ترتيب تشغيل الحركات عند عرض الشريحة. كما ترى فإن الحركة Appear سريعة وتكاد لا تُلاحظ. ولذلك سنقوم بإظهار كلمة بعد أخرى بدلا من إظهار العنوان كاملا. لكن خيارات التأثير لا تحتوي سوى على خيار واحد وهو إظهار النص كعنصر واحد: لذلك سنعرض الخيارات الإضافة للتأثير من مشغل الخيارات الإضافية: في مربع حوار الخيارات الإضافية يمكنك تغيير تسلسل حركة النص كعنصر واحد، حسب الكلمات، أو حسب الحروف من خانة Animate Text. كما يمكنك تحديد الفترة الزمنية بين الحركات من خيار التأخير Delay. سنقوم باختيار حركة ظهور النص حسب الكلمة By word، ونبقي على القيمة الافتراضية للتأخير (0.5 sec)، وستكون النتيجة كالتالي: إذا كانت حركة ظهور الكلمات سريعة يمكنك زيادة قيمة التأخير. أما نصوص المحتوى الرئيسي فسنقوم بتطبيق حركة مختلفة عليها، ولتكن إحدى حركات التوكيد؛ حركة Object Color مثلا: لكن عند تغير لون النص إلى اللون البرتقالي يجعله صعب القراءة، لذلك سأقوم بتغيير لون النص الأصلي من الأبيض إلى الأسود الباهت: ثم أغير لون الحركة من خيارات التأثير إلى اللون الأزرق الفاتح: بهذه الطريقة سيتغير اللون أثناء الحركة من اللون الأسود الباهت إلى الأزرق الفاتح، مما يجعله أكثر جذبا للانتباه: بالإمكان أيضا جعل لون النص باهتا بعد أن تنتهي الحركة في كل فقرة وتقليل السرعة وذلك من خلال الخيارات الإضافية. في تبويب Effect الخاص بالتأثيرات الإضافية قم بتغيير اللون الذي تريد إظهاره بعد انتهاء الحركة في الفقرة من خانة After Animation، سأقوم هنا باختيار نفس اللون الأصلي للنص، أسود باهت: ومن تبويب Timing قم بتحديد السرعة المرغوبة للانتقال من فقرة إلى أخرى من خانة Delay، يناسبني التأخير 2 ثانية لذلك سأقوم بتحديده: بعد الانتهاء انقر موافق لمعاينة تأثير الحركة وسرعته: جرب تطبيق العديد من الحركات وتأثيراتها واستخدم أمر معاينة Preview لتشغيل الحركات ومعاينتها إلى أن تحصل على النتيجة المرغوبة. تحريك الصوريمكنك تطبيق الحركات على الصور بنفس طريق تطبيقها على النصوص. المثال التالي هو عبارة عن شريحة تحتوي على مجموعة من الصور مع عناوينها داخل أشكال. سأقوم بتحديد الصورة الأولى في اليسار وتطبيق حركة Wipe عليها. من خيارات التأثير سأختار اتجاه الحركة إلى الأسفل: ثم سأقوم بتحديد الشكل الأول على اليسار (عنوان الصورة) وتطبيق حركة Color Pulse عليه. من خيارات التأثير سأختار اللون الأصفر بدلا من البرتقالي: سأستخدم أداة ناسخ الحركة Animation Painter لنسخ حركة الصورة الأولى والشكل الأول وتطبيقها على الصور والأشكال الأخرى. عند استخدام ناسخ الحركة، حدد عنصر مصدر الحركة أولا (الصورة الأولى في هذا المثال)، انقر بشكل مزدوج على ناسخ الحركة، ثم انقر على الصورة الثانية، ثم الصورة الثالثة، وهكذا. بعد الانتهاء من النسخ قم بالنقر فوق ناسخ الحركة مجددا لإلغاء تفعيله: سأكرر نفس الخطوة على الأشكال لنسخ حركتها: لكن لاحظ أن تسلسل ظهور الحركات غير مرتب. أرغب في جعل الصورة تظهر أولا ثم عنوانها، بعدها الصورة الثانية ثم عنوانها. لتغيير تسلسل الحركات سنقوم بفتح جزء الحركة Animation Pane من تبويب حركات Animations: يحتوي جزء الحركة على جميع الحركات المطبقة على جميع العناصر، ويمكنك من خلاله التحكم بترتيب تشغيل الحركات ووقت ومدة تشغيلها. عندما تقوم بتحديد العنصر في الشريحة سيتم تحديد الحركة المطبقة عليه في جزء الحركة. لتغيير ترتيب الحركة لأي عنصر من العناصر قم بتحديده في جزء الحركة واسحبه إلى الموضع الذي تريد تشغيله عنده. سأقوم بتغيير ترتيب الشكل الثاني من 5 إلى 4 ليتم تشغيله بعد الصورة الثانية (واسمها Picture 6) في هذا المثال: والآن أصبح تشغيل الحركة مرتبا: لاحظ أن حركة الصورة تشغل أولا ثم حركة الشكل. وهذا يعني أنه عند تشغيل العرض التقديمي يجب أن تنقر بالفأرة لتشغيل حركة الصورة الأولى، ثم تنقر مرة أخرى لتشغيل حركة الشكل الأول، ثم تنقر لتشغيل حركة الصورة الثانية وهكذا. لجعل حركتي الصورة والشكل تُشغلان معا انقر بزر الفأرة الأيمن على حركة الشكل في جزء الحركة واختر Start With Previous لبدء تشغيل حركة الشكل مع حركة الصورة: تمثل الأشرطة الصفراء والخضراء مدة تشغيل الحركة. قم بتمرير الفأرة فوقها إلى أن يتغير شكل المؤشر إلى متجهين صغيرين. اسحب إلى اليمين لزيادة المدة، أو إلى اليسار لتقليلها. يمكنك الاستفادة من العلامة التي تظهر أثناء السحب لمعرفة المدة. سأقوم مثلا بزيادة مدة حركة الصور إلى 1.5 ثانية: بعد الانتهاء من جميع الإعدادات قم بمعاينة التغييرات من أمر معاينة Preview، أو اضغط مفتاحي Shif +F5 لتشغيل العرض من الشريحة الحالية: تحريك المخططاتعندما يتعلق الأمر بتحريك المخططات فإنّ اختيار نوع الحركة المناسبة للمخطط مهم جدا. إذ أن هناك حركات تبدو غير ملائمة عند تطبيقها على نوع معين من المخططات. لنأخذ المخطط أدناه كمثال: فلو اخترت حركة مثل Swivel أو Bounce لمثل هذا النوع من المخططات لن تبدو منطقية. لذلك من الأفضل تجربة أكثر من حركة لاختيار الأنسب من بينها. سأقوم بتطبيق حركة Float In على المخطط. ومن خيارات التأثير سأختار تتابع الحركة Sequence حسب السلسلة By Series (أي تظهر سلسلة Flow أولا، بعدها سلسلة Stability، وأخيرا سلسلة bulk specific gravity): وستكون نتيجة الحركة كالتالي عند تشغيلها: إذا كنت ترغب في جعل خطوط شبكة المخطط ثابتة وبقية العناصر متحركة تستطيع حذف حركتها. حدد الرقم 1 من حركات المخطط واضغط Delete من لوحة المفاتيح لحذف الحركة الأولى وهي الخاصة بالشبكة. وإذا كان لديك مخطط دائري (كما في المثال أدناه) يمكنك اختيار حركات مثل Wheel: (صورة 33) وبنفس الطريقة يمكنك تطبيق الحركات على رسومات SmartArt. من الحركات المناسبة Fade، Wipe أو Zoom. سنقوم بتطبيق حركة Wipe على المخطط التالي، ومن خيارات التأثيرات سنختار اتجاه الحركة من الأعلى From Top ونوع التتابع Level at Once لعرض المستوى الأول ثم الثاني، ثم الثالث، إلخ: وستكون نتيجة الحركة النهائية كالتالي: وبالطبع يمكنك تغيير سرعة الحركة من الخيارات الإضافية كما فعلنا في الأمثلة السابقة. في المثال أدناه لدي ثلاثة تروس أرغب في إضافة حركة دوران إليها: سأقوم أولا بتحديد الترس الأزرق، وأطبق حركة Spin عليه، وهي أكثر حركة مقاربة لدوران التروس. من خيارات التأثير الإضافية سأقوم بزيادة المدة Duration إلى 5 ثانية لجعل حركة الدوران بطيئة: سأستخدم ناسخ الحركة Animation Painter لتطبيق نفس الحركة على الترسين الآخرين. وبما أن حركة التروس المتداخلة تكون واحدة عكس الأخرى، لذلك سأقوم بتحديد الترس الوردي وعكس حركته لتكون عكس حركة الترس الأزرق (أي عكس عقارب الساعة Counterclockwise) من خيارات التأثير: ومن جزء الحركة Animation Pane سأجعل حركة الترسين الوردي والأخضر تبدأ مع حركة الترس الأزرق Start With Previous: وأخيرا سأقوم بمعاينة الحركة من أمر معاينة Preview، وستبدو بالشكل التالي: قد لا تبدو الحركة مثالية (من الناحية الميكانيكية) لكنها تعطيك تصورا عما يمكنك فعله مع خيارات الحركة المتوفرة وإنشاء عروض تقديمية مميزة. إنشاء حركات مخصصة باستخدام مسارات الحركةفي حركات الدخول، التوكيد، والخروج يمكنك التحكم باتجاه الحركة وتتابعها من خيارات التأثير. لكن لا يمكنك أن تتحكم بموضع بدء الحركة ولا مسارها. للتحكم بمثل هذه الخيارات استخدم مسارات الحركة Motion Paths. قم بتحديد الشكل الذي تريد تطبيق مسار الحركة عليه واختر أحد المسارات من معرض الحركات: يمثل الخط مسار الحركة، النقطة الخضراء بداية الحركة، والنقطة الحمراء نهاية الحركة. الخطوات التالية هي أمثلة توضيحية عما يمكن تطبيقه باستخدام مسارات الحركة. حدد النقطة الحمراء وقم بتحريكها تجاه الشكل 3 إلى أن يتطابق الشكلين معا، ثم انقر معاينة، ستلاحظ أن الشكل 1 قد تحرك خلف الشكل 3: بنفس الطريقة طبق مسار الحركة Lines على الشكل 2، ثم حركه باتجاه الشكل 3 إلى أن يتطابق معه. انقر معاينة لمشاهدة الحركة: يمكنك اختيار مسارات أخرى، كالأقواس أو المسارات الدائرية. وإذا رغبت برسم مسار مخصص يدويا يمكنك استخدام المسار المخصص Custom Path: يمكنك أيضا تطبيق أكثر من حركة على نفس العنصر. حدد العنصر الذي ترغب في تحريكه، وطبق إحدى الحركات عليه من معرض الحركات، ولتكن مسار مقوس مثلا. ثم انقر فوق إضافة حركة Add Animation من نفس التبويب واختر الحركة الثانية، سأختار هنا Spin: من جزء الحركة Animation Pane اجعل الحركة الثانية بعد مع الحركة الأولى: يمكنك الوصول إلى خيارات التأثير الإضافية Effect Options بالنقر على الحركة بالزر الأيمن في جزء الحركة أيضا. قم بإجراء التغييرات المرغوبة من خيارات التأثير، وحدد Auto-reverse إذا كنت ترغب بعكس الحركة أيضا: انقر معاينة لمشاهدة النتيجة، أو اضغط مفتاحي Shift+F5 لبدء العرض من الشريحة الحالية:
  12. هذا الدرس الأول من سلسلة نصائح وحيل فوتوشوب، التي سنتعلم من خلالها العديد من الحيل والأدوات عند التصميم ببرنامج فوتوشوب بالإضافة إلى مجموعة من النصائح حول الإستخدام الأمثل للبرنامج. سنتعلم في هذا الدرس كيفية تصميم شريط إعلاني (Banner) متحرك صغير وبسيط بخطوات سريعة وبسيطة. افتح ملفا جديدا في برنامج فوتوشوب بحجم 400×75 بكسل. طبّق على الخلفية تدرّج لوني كما في الصورة. ارسم تحديد دائري يظهرُ طرفهُ فقط في الجزء الأيسر من الشريط. امسح هذا الجزء المحدد. أبقِ على التحديد وارسم بداخله تدرج لوني مطابق للخلفية مع عكس اتجاهه. أبقِ على التحديد أيضًا ثم اذهب للقائمة: Select > Modify > Contract وأدخل القيمة 5 وبعدها اضغط OK ثم طبّق تدرّج لوني على ما بقي من التحديد من الرمادي الفاتح إلى الأبيض كما في الصورة. أدخل الشعار في هذا الجزء الرمادي الفاتح. أدخل عنوان الشريط الرئيسي في الموقع الذي تراه مناسبًا. أدخل العنوان الفرعي في المساحة المتبقية مع جعلها بحجم خط أصغر وبألوان متناسقة مع التصميم بصورة عامة (علمًا أنّه يوجد العديد من العناوين الفرعية ولكننا سنقوم بإدخالها لاحقًا). انسخ طبقة النص الفرعي بالضغط على Ctrl+J بعد تحديد طبقة النص طبعًا ثم حدد النسخة واذهب للقائمة: Filter > Blur > Motion Blur ثم أدخل القيمة 12 وبعدها OK (سيسألك لدى تنفيذ هذا الفلتر عن موافقتك على تحويل الطبقة إلى صورة نقطية فاضغط موافق). أخفِ هاتين الطبقتين ثم أدخل العنوان الفرعي الثاني في طبقة جديدة وكرّر عملية تطبيق الفلتر عليه بذات الأسلوب. كرّر العملية مع جميع العناوين الفرعية ثم فعّل نافذة TimeLine من قائمة Window ثم أدخل الأطر تباعًا مع إظهار النص الفرعي أولًا فقط ثم النص الفرعي الأول مموّه بالفلتر ثم النص الفرعي الثاني وهكذا حتى النهاية مع جعل مدّة عرض إطار النص الفرعي العادي 1 ثانية ومدّة عرض النص الفرعي المموّه 0.1 ثانية. اذهب إلى القائمة: File > Save to Web ثم احفظ الملف بصيغة GIF مع تخصيص الإعدادات المناسبة والنتيجة ستكون كالتالي:
  13. إن عالم الويب أصبح جزءًا لا يتجزأ من حياتنا اليومية هذا ما يجعلنا نبتكر طُرقًا وأساليبَ جديدة ليكون قريبًا منا أكثر. نحنُ كمطوري ويب بحاجة دائمًا إلى إضافةِ لمساتٍ ساحرة وتصاميمَ مبتكرة لإنعاش موقع الويب والتفرّد بعنصر الإبداع في إظهار الموقع بأبهى حلّة وأجمل تصميم. سأضع بين يديك مقدمة لأهم خيارين قد يختار منهما مطوّر الويب عند الشروع في بناء وتصميم محتوى وعناصر موقع الويب. الخيار أو الأسلوب الأوّل وهو الأكثر شهرة بحكم قدمه هو العمل مع عناصر DOM في HTML هذا النهج الذي تستخدمه أنت و 99% من المطورين في العالم الذي يعتمد على إنشاء HTML ،CSS، و JavaScript ليكون لديك عناصر ورسومات تُظهرها بإبداعك الخاص. النهج الثاني والذي ظهر بظهور HTML5 وهو استخدام عنصر <canvas>. والذي يتيح لك أن تجرب وتتخيل الرسم بطريقةٍ أخرى وأكثر متعة غير تلك التي ألِفناها. إنّ كُلًّا من هذين الخيارين له استخدامه الخاص الذي يعتمد بالدرجة الأولى على درجةِ تعقيدِ عنصر التصميم الذي تودُّ إنشاءه، سأقوم بعرض لمحة سريعة عن الفروقات بين المنهجيتين واستخدام كل منهما. إن عملية ترجمة محتوى الصفحة وإظهارها على المتصفّح تسير وفق نظامين هما نظام وضع الاحتفاظ (retained mode (Dom والنظام الحالي أو الفوري (Immediate Mode (canvas. نظام وضع الاحتفاظ (Dom) في هذا النظام تقوم بإرسال العناصر والمحتويات التي قمتَ بإنشائها إلى Graphics API والذي بدوره يقوم بإظهارها على المتصفّح. في الشكل التالي توضيح لكيفية حدوث نظام وضع الاحتفاظ retained mode: النظام الحالي أو الفوري (Canvas) النظام الفوري أو الحالي الذي يعتمد على استخدام <canvas> يتمتع بلياقة عالية تجعله أهلًا لرفع الأحمال الثقيلة heavy lifting فإنك لا تقوم بتحديد ما ستود رسمه فقط بل تقوم بإنشاء وصيانة التصميم أي أن Graphics API الذي قام بالكثير من أجلك في نظام وضع الاحتفاظ retained mode لا يقوم بالشيء الكثير هنا. في الشكل التالي توضيح لكيفية حدوث النظام الفوري أو الحالي Immediate mode: بمجمل الأحوال فإن استخدام عنصر <canvas> أسرع بكثير من استخدام نظام وضع الاحتفاظ retained mode كما أنه يوفّر مرونة كبيرة مقارنة بوضع الاحتفاظ وخاصة في التّعامل مع عناصر كثيرة. توجد سيئة واحدة في استخدام <canvas> وهي في حال العمل على مساحة واسعة سيكون هناك نوعًا من البطء في الأداء. لا يمكنك تخيل ما قد تستطيع عمله في هذه الأداة فبإمكانك القيام برسومات بيانية، إنشاء رسوم بتأثيرات حركية Animations وعمل تراكيب صور photo Compositions أو حتى القيام بمعالجة الفيديو. تدعم Canvas جميع المُتصّفحات الحديثة: فيرفكس (الإصدار 1.5 وما فوق). safari و OS X Dashboard (على نظام ماك). IE (الإصدار 9 وما فوق). Chrome و Opera. لنبدأ الآن بالتعرف على عنصر <canvas> عن قرب وتَعلُّم كيفيّة إنشاء سياق لوحة ثنائي الأبعاد وتقوم برسم أول مثال لك على متصفّحك. الرقعة Canvas يبدو لنا للوهلة الأولى أن عنصر <canvas> يشبه عنصر <img> مع فارق واضح وكبير هو أن عنصر <canvas> ليس لديه خاصيّة src و alt. عنصر <canvas> لديه خاصيتان وحيدتان فقط هما العرض width والطول height، القيم الافتراضية هي 300 بكسل للعرض و 150 بكسل للطول. ككل عناصر HTML فإن عنصر <canvas> يعرف كوسم: <canvas id="tutorial" width="150" height="150"> </canvas> لا تعتبر الخاصيّة id خاصيّة محددة بالرُّقعة <canvas> ولكنها واحدة من الخصائص العامة لـHTML global Html attribute. يمكن تصميم عنصر <canvas> كأي عنصر صورة image وتحديد الخصائص مثل (margin ،border ،background، ...) مثل هذه الخصائص لا تؤثر على عملية الرسم الفعلي هي فقط تحدد الشكل العام للوحة <canvas>. المحتوى الاحتياطي Fallback Content بالرّغم من أنه لا يتم إظهار أو تشغيل عنصر Canvas في المتصفّحات غير الداعمة للـ HTML5 إلا أنه يمكنك إنشاء محتوى احتياطي fallback content ليحل محل <canvas> في المتصفّحات ذات الإصدارات القديمة نوعًا ما والتي لا تدعم HTML5 مثل إصدارات Internet Explorer IE السابقة للإصدار 9. يجب أن توفر دائمًا محتوى احتياطي في حال استخدامك لعنصر الرُّقعة <canvas> ليتم إظهارها على جميع أنواع وإصدارات المتصفّحات التي لا تدعمها. لتوفير محتوى احتياطي ستحتاج إلى إضافة نص أو صورة داخل وسم <canvas> بحيث حين يتم تشغيل الصفحة في متصفّح لا يدعم Canvas سيقوم المتصفّح بتجاهل العنصر الحاوي على المحتوى الاحتياطي وهو عنصر canvas ومن ثم إظهار المحتوى الاحتياطي الذي بداخلها. أما في حال دعم المتصفّح لعنصر Canvas فسيقوم بتجاهل المحتوى الاحتياطي ويقوم بعمل rendering تصيير لعنصر <canvas> بشكل طبيعي. على سبيل المثال لنقم بإنشاء <canvas> وتوفير محتوى احتياطي لها، سأقوم بعمل محتوى احتياطي عبارة عن نص وكذلك مثال آخر يكون المحتوى الاحتياطي فيه عبارة عن صورة <img>: <canvas id="stockGraph" width="150" height="150"> current stock price: $3.15 +0.15 </canvas> <canvas id="clock" width="150" height="150"> <img src="images/clock.png" width="150" height="150" alt=""/> </canvas> وسم الإغلاق </canvas> لا بد أنك لاحظت أن الوسم <img> مثلًا لا يتطلب وسم إغلاق ولا تتأثر بذلك باقي العناصر، عنصر في حين أن عنصر canvas يحتاج لوضع وسم الإغلاق </canvas> هو وسم مطلوب required وذلك لأنه في حال عدم وضعه سيتم اعتبار كل شيء في الصفحة بعد الوسم <canvas> هو عبارة عن محتوى احتياطي ولن يتم إظهاره. سياق التصيير The rendering Context يقوم عنصر <canvas> بإنشاء سطح ذو قياس ثابت يتسع لأكثر من سياق تصيير rendering context التي يتم استخدامها لإنشاء والتعامل مع المحتوى المعروض. سنركز هنا على سياق التصيير ثنائي الأبعاد 2D rendering context. يوجد سياقات أخرى توفر أنواعًا مختلفة من التصيير rendering مثل السياق ثلاثي الأبعاد WebGL الذي يرتكز على OpenGL ES. بطبيعة الحال عند إنشاء <canvas> ستكون فارغة ولإظهار شيء فإن السكربت يحتاج للوصول إلى سياق التصيير Rendering Context والرسم عليه. عنصر <canvas> يحتوى على دالة method تسمى ()getContext تستَخدم لتطبيق سياق التصيير Rendering Context ودوال الرسم الخاصة به، تأخذ الدالة ()getContext معاملًا واحدًا one parameter وهو نوع السياق، للرسومات ثنائية الأبعاد 2D Graphics نقوم بتحديد “2d” لنحصل على سياق تصيير ثنائي الأبعاد Canvas RenderingContext2D. كما في المثال التالي: var canvas = document.getElementById('tutorial'); var ctx = canvas.getContext('2d'); يجلب السطر الأول من السكربت العنصر <canvas> من خلال استدعاء الدالة ()document.getElementById، ثم تحديد نوع السياق عن طريق الدالة ()getContext. التأكد من الدعم Checking for support شرحنا في البداية أن المحتوى الاحتياطي يظهر في المتصفّحات التي لا تدعم عنصر <canvas> يمكن أيضًا للسكربت أن يقوم بالتأكُّد من الدّعم برمجيًا من خلال اختبار بسيط لوجود الدالة ()getContext. لنقم بتعديل الشيفرة البرمجية أعلاه ونستخدم السكربت في التأكد من دعم المتصفّح لعنصر <canvas> ليصبح على النحو التالي: var canvas = document.getElementById('tutorial'); if (canvas.getContext){ var ctx = canvas.getContext('2d'); // drawing code here } else { // <canvas> unsupported code here } قالب الهيكل Skeleton Template سأقوم ببناء قالب أساسي لاستخدامه كنقطة انطلاق لأمثلتنا اللاحقة. ملاحظة: ليس من الأمور الجيدة تضمين السكربت في وسم HTML ولكن قمت بذلك للحفاظ على المثال موجز ومختصر. <!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title>canvas tutorial</title> <script type="text/javascript"> function draw(){ var canvas = document.getElementById('tutorial'); if (canvas.getContext){ var ctx = canvas.getContext('2d'); } } </script> <style type="text/css"> canvas { border: 1px solid black; } </style> </head> <body onload="draw();"> <canvas id="tutorial" width="150" height="150"> </canvas> </body> </html> يحتوي السكربت على دالة تدعى ()draw التي تُنّفذ في حين الانتهاء من تحميل صفحة الويب، يتم ذلك عن طريق الاستماع للحدث load في الصفحة حيث يتم استدعاءه باستخدام ()window.setTimeout و ()window.setInterval أو أي معالج حدث آخر event handler طالما أنه يتم تحميل الصفحة أولًا. عند تنفيذ السكربت أعلاه سيظهر لنا الشكل التالي في صفحة الويب: تطبيق مثال بسيط دعونا نلقي نظرة على مثال بسيط يقوم برسم مستطيلين متقاطعين أحدهما يحوي على شفافية لونية alpha transparency. <!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <script type="application/javascript"> function draw() { var canvas = document.getElementById("canvas"); if (canvas.getContext) { var ctx = canvas.getContext("2d"); ctx.fillStyle = "rgb(200,0,0)"; ctx.fillRect (10, 10, 55, 50); ctx.fillStyle = "rgba(0, 0, 200, 0.5)"; ctx.fillRect (30, 30, 55, 50); } } </script> </head> <body onload="draw();"> <canvas id="canvas" width="150" height="150"> </canvas> </body> </html> اعتمادًا على القالب الأساسي الذي أنشأتُه وضعت السكربت الخاص باستخدام سياق التصيير ()Rendering Context getContext ضمن الشرط if وذلك ليتم تنفيذه في حال تحقق وجود دعم للعنصر <canvas> من قِبل المتصفّح. تقوم الدالة ()getContext بإرجاع متغير يمكن اعتباره غرض object يحوي على مجموعة دوال تقوم بعمليات الرسم وإنشاء الأشكال. الخاصيّة fillStyle تقوم بتحديد اللّون الذي سيتم به تلوين العنصر التالي، تأخذ الخاصيّة fillStyle اللّون بنظام (RGB (Red, Green, Blue والشفافية opacity. لاحظ أنه تم تلوين المستطيل الأول باللون الأحمر حيث أخذ قيمة 200 في حقل red، والمستطيل الثاني بلون أزرق مع تحديد الشفافية opacity=0.5 أي سيكون ذو شفافية لونية بنسبة 50% (تأخذ الخاصيّة opacity قيمها من 0.0 -1.0). الدالة ()FillRect ترسم مستطيل ذو مساحة لونية كاملة solid color وذلك بتحديد إحداثيات النقاط الأربع للمستطيل الذي نود رسمه ابتداءً من الزاوية اليسارية العليا التي تأخذ احداثيات المركز (0,0). كانت هذه أبرز النقاط التي تحيطك بالمفاهيم الأساسية لاستخدام عنصر canvas في الدروس المقبلة ستكون الشروحات غنية للغاية وسترى إمكانيات مذهلة لعنصر canvas تشحذ أفكارك الابداعية بامتياز. المصادر
  14. رغم أنّ تحويلات CSS3 ثلاثية الأبعاد صار لها فترةً لا بأس بها من الزمن، إلّا أنّني اكتشفت عدم امتلاك الخبرة الكافية للعمل معها بعد. أستخدم Windows 8 منذ فترة من الوقت، ومن أوّل الأمور التي لفتت نظري كانت الانتقالات transitions والتحريكات animations المبنية ضمن لوح البداية Start Dashboard، لذلك خطرت ببالي فكرة رائعة، وهي لماذا لا تكون خبرتي الأولى مع تحويلات CSS3 ثلاثية البعد ببناء تطبيق يماثل في سلوكه تلك التحريكات والتأثيرات في Windows 8؟ وهذا ما حدث في هذا الدرس. سأستخدم خصائص CSS بدون أي بادئة prefix وذلك بغرض الاختصار، لكنك ستجد الخصائص كاملة ضمن النص المصدري للمشروع على Github. ستعمل مقاطع الشيفرة التي ستجدها هنا على متصفحات تدعم خصائص CSS المستخدمة. الرماز The Markupبنية هذا التطبيق بسيطة: يتكون لوح البداية من قائمة من القطع tiles بثلاثة قياسات وهي الصغير، الكبير، والكبير جدًا. لكل قطعة من هذه القطع صفحة page مرتبطة معها. والصفحة عبارة عن تغطية overlay تظهر عند النقر على إحدى القطع في لوح البداية. سنعتبر الصفحة أنّها تُحاكي تطبيق سطح مكتب في Windows 8، فتكون القطعة كما هو واضح اختصارًا له (للصفحة). عند النقر على قطعة ستُفتح الصفحة الموافقة لها. يوجد نوعان من الانتقالات للصفحة بعد فتحها يدعمهما اللوح في Windows 8. يفتح أحدهما الصفحة بتأثير دوران ثلاثي الأبعاد اعتبارًًا من يمين الشاشة، أمّا الآخر فتنزلق فيه الصفحة من وإلى اليسار. سنعرّف صنف CSS لكل نوع من نوعيّ الصفحة، حيث سيكون الصنف s-page للصفحات التي تنزلق من وإلى اليسار، أمّا الصنف r-page فسيكون للصفحات التي تدور من اليمين. ينبغي علينا من أجل كل قطعة تعيين نوع الصفحة التي ستفتحها القطعة (بالاعتماد على التأثير الذي نريده من أجل هذه الصفحة). سنعرّف نوع الصفحة لكلّ قطعة باستخدام سمة attribute مخصّصة سنسميها data-type-page، ستهتم هذه الـسمة بتطبيق أسماء أصناف CSS الصحيحة التي ستفعّل التحريكات المناسبة فيما بعد. يجب أن يكون لكل صفحة اسم. سيختلف اسم الصفحة لتطبيق معيّن عن اسم الصفحة لتطبيق آخر، فمثلًا الـقطعة المسمّاة Skype ستفتح صفحة اسمها skype-app وهكذا دواليك. لقد استخدمت اسميّ صفحة فقط في هذا المثال، وقد كرّرتهما من أجل جميع الـقطع الباقية بغرض التبسيط، كما استخدمت الاسم custom-page لآخر قطعة وذلك على سبيل المثال. ربما تحتاج أن تضيف صفحة مختلفة لكل قطعة، وهذا يعني اسم صفحة مختلف لكلٍّ منها. إليك الرماز الخاص بكامل اللوح (الـقطع والصفحات): <div class="demo-wrapper"> <div class="s-page random-restored-page"> <div class="page-content"> <h2 class="page-title">Some minimized App</h2> <div class="close-button s-close-button">x</div> </div> </div> <div class="s-page custom-page"> <div class="page-content"> <h2 class="page-title">Thank You!</h2> <div class="close-button s-close-button">x</div> </div> </div> <div class="r-page random-r-page"> <div class="page-content"> <h2 class="page-title">App Screen</h2> <p>Chew iPad power cord chew iPad power cord attack feet chase mice leave dead animals as gifts and stick butt in face chew iPad power cord. Chase mice. Run in circles use lap as chair why must they do that. Intrigued by the shower destroy couch leave hair everywhere sleep on keyboard chew iPad power cord. Use lap as chair. Missing until dinner time stand in front of the computer screen, intently sniff hand. Find something else more interesting. Destroy couch play time so inspect anything brought into the house hate dog burrow under covers. Sleep on keyboard destroy couch so hate dog so hide when guests come over. Chase mice destroy couch lick butt throwup on your pillow use lap as chair yet intrigued by the shower but climb leg. Stare at ceiling make muffins or hunt anything that moves claw drapes. Intently sniff hand intrigued by the shower. Why must they do that. Cat snacks leave dead animals as gifts or inspect anything brought into the house sweet beast so stare at ceiling give attitude. Flop over claw drapes but sun bathe lick butt, and chase mice. Rub face on everything lick butt leave hair everywhere lick butt, missing until dinner time for use lap as chair lick butt. Make muffins leave dead animals as gifts play time. Chew foot intrigued by the shower stare at ceiling inspect anything brought into the house yet hopped up on goofballs. Hunt anything that moves intently sniff hand for hunt anything that moves play time. Chew foot climb leg throwup on your pillow so lick butt yet make muffins hate dog. Intrigued by the shower. Intently sniff hand shake treat bag. Cat snacks burrow under covers make muffins but all of a sudden go crazy find something else more interesting. Flop over chase mice. Give attitude. Inspect anything brought into the house. Stick butt in face sun bathe so find something else more interesting and intrigued by the shower. Rub face on everything use lap as chair. Under the bed claw drapes chase mice but leave hair everywhere yet make muffins yet claw drapes. Use lap as chair. Find something else more interesting stretch for under the bed. Nap all day intrigued by the shower, hate dog sweet beast intently sniff hand so hate dog nap all day. Swat at dog hide when guests come over and mark territory chase mice for cat snacks. Use lap as chair. Lick butt throwup on your pillow need to chase tail. Mark territory. Stick butt in face shake treat bag yet hunt anything that moves, yet hopped up on goofballs yet stare at ceiling under the bed. Give attitude chase imaginary bugs stretch so hunt anything that moves so hide when guests come over but intrigued by the shower find something else more interesting. Make muffins behind the couch for chew foot. Sweet beast flop over but throwup on your pillow. Intently sniff hand use lap as chair and missing until dinner time and chase imaginary bugs. </p> </div> <div class="close-button r-close-button">x</div> </div> <div class="dashboard clearfix"> <ul class="tiles"> <div class="col1 clearfix"> <li class="tile tile-big tile-1 slideTextUp" data-page-type="r-page" data-page-name="random-r-page"> <div><p>This tile's content slides up</p></div> <div><p>View all tasks</p></div> </li> <li class="tile tile-small tile tile-2 slideTextRight" data-page-type="s-page" data-page-name ="random-restored-page"> <div><p class="icon-arrow-right"></p></div> <div><p>Tile's content slides right. Page opens from left</p></div> </li> <li class="tile tile-small last tile-3" data-page-type="r-page" data-page-name="random-r-page"> <p class="icon-calendar-alt-fill"></p> </li> <li class="tile tile-big tile-4" data-page-type="r-page" data-page-name="random-r-page"> <figure> <img src="images/blue.jpg" /> <figcaption class="tile-caption caption-left">Slide-out Caption from left</figcaption> </figure> </li> </div> <div class="col2 clearfix"> <li class="tile tile-big tile-5" data-page-type="r-page" data-page-name="random-r-page"> <div><p><span class="icon-cloudy"></span>Weather</p></div> </li> <li class="tile tile-big tile-6 slideTextLeft" data-page-type="r-page" data-page-name="random-r-page"> <div><p><span class="icon-skype"></span>Skype</p></div> <div><p>Make a Call</p></div> </li> <li class="tile tile-small tile-7 rotate3d rotate3dX" data-page-type="r-page" data-page-name="random-r-page"> <div class="faces"> <div class="front"><span class="icon-picassa"></span></div> <div class="back"><p>Launch Picassa</p></div> </div> </li> <li class="tile tile-small last tile-8 rotate3d rotate3dY" data-page-type="r-page" data-page-name="random-r-page"> <div class="faces"> <div class="front"><span class="icon-instagram"></span></div> <div class="back"><p>Launch Instagram</p></div> </div> </li> </div> <div class="col3 clearfix"> <li class="tile tile-2xbig tile-9" data-page-type="custom-page" data-page-name="random-r-page"> <figure> <img src="images/summer.jpg" /> <figcaption class="tile-caption caption-bottom">Fixed Caption: Some Subtitle or Tile Description Goes Here with some kinda link or anything </figure> </li> <li class="tile tile-big tile-10" data-page-type="s-page" data-page-name="custom-page"> <div><p>Windows-8-like Animations with CSS3 & jQuery © Sara Soueidan. Licensed under MIT.</p></div> </li> </div> </ul> </div> </div>حصلت على خط الأيقونة الذي استخدمته من Icomoon. الذي سيحدث الآن: ستحصل JavaScript على اسم ونوع الصفحة المراد فتحها عند نقر القطعة، وبعد ذلك، ووفقًا لنوع الصفحة ستعمل JavaScript على تطبيق أسماء أصناف CSS المناسبة على الصفحة (والتي سنحصل على اسمها أيضًا من السمة data-page-name) لفتحها بنمط تحريك معيّن لكل صنف CSS يتم تطبيقه. تنسيقات CSSأرجو ملاحظة أنّني أستخدم أنماط تنسيق تراعي الأجهزة المحمولة أولًا mobile-first، والتي سنجعلها لاحقًا ذات استجابية responsive عالية ضمن قسم استعلامات الوسائط media queries في CSS. سنتناول في البداية التنسيقات الخاصة بالحاوية (عنصر div) والتي ستحوي كامل المثال التوضيحي. سنعرّف تنسيقات عامّة ونتأكّد من ضبط الخاصية perspective بحيث يؤدي ذلك إلى تفعيل الفضاء ثلاثي البعد 3D، وإلّا سيبدو كامل المثال بشكل منبسط أي ثنائي البعد 2D. .demo-wrapper { padding: 2em .5em; width: 100%; height:100%; perspective: 3300px; position: relative; }لنبدأ الآن بتنسيقات وتحريكات لوح البداية. ستُنفَّذ أوّل تحريكة سنطبّقها على لوح البداية عند تحميل الصفحة ضمن متصفّح الويب. سيكون لوح البداية مخفيًّا في يمين الشاشة بادئ الأمر، ثمّ يظهر تدريجيًّا مع الانتقال إلى موقعه الأساسي عند تحميل الصفحة. .dashboard { margin: 0 auto; width: 100%; padding: 1em; transform: translateX(200px); opacity:0; animation: start 1s ease-out forwards; } @keyframes start{ 0%{ transform: translateX(200px); opacity:0; } 50%{ opacity:1; } 100%{ transform: translateX(0); opacity:1; } }يتضاءل لوح البداية ويختفي عند نقر قطعة منه. حيث ينتقل اللوح على طول محور z، ويتضاءل حجمه، كما تنخفض قيمة الخاصية opacity له تدريجيًا حتى تصبح في النهاية تساوي الصفر مما يعطي شعورًا بأنّ اللوح يختفي بالتدريج. أمّا عندما يُغلق المستخدم الصفحة فإنّ لوح البداية يعود للظهور مرّة أخرى. بالنسبة للأعمدة الثلاثة في لوح البداية فإنّها تظهر تدريجيًّا واحدًا تلو الآخر مع تأخير زمني طفيف بينها. عندما تُغلق الصفحة، سيُضاف اسم صنف CSS لكل عمود (بواسطة JavaScript) وكل من هذه الأصناف ستُفعّل تحريكة بتأخير زمني مُحدّد. فيما يلي أصناف CSS والتحريكات المطبّقة على لوح البداية عند نقر القطع tiles وإغلاق الصفحات. .fadeOutback{ animation: fadeOutBack 0.3s ease-out 1 normal forwards; } .fadeInForward-1, .fadeInForward-2, .fadeInForward-3 { opacity:0; transform: translateZ(-5em) scale(0.75); animation: fadeInForward .5s cubic-bezier(.03,.93,.43,.77) .4s normal forwards; } .fadeInForward-2{ animation-delay: .55s; } .fadeInForward-3{ animation-delay: .7s; } @keyframes fadeOutBack{ 0% {transform: translateX(-2em) scale(1); opacity:1;} 70% {transform: translateZ(-5em) scale(0.6); opacity:0.5;} 95% {transform: translateZ(-5em) scale(0.6); opacity:0.5;} 100% {transform: translateZ(-5em) scale(0); opacity:0;} } @keyframes fadeInForward{ 0% {transform: translateZ(-5em) scale(0); opacity:0;} 100% {transform: translateZ(0) scale(1); opacity:1;} }وبالنسبة لتنسيقات الصفحات: .r-page { width: 100%; height: 100%; text-align: center; font-size: 2em; font-weight: 300; position: absolute; right: 0; top: 0; left:0; bottom:0; opacity: 0; color: white; z-index: 10; padding:10px; transform-origin: 100% 0%; transform: rotateY(-90deg) translateZ(5em) } .s-page { color: white; z-index: 10; text-align: center; font-size: 2em; font-weight: 300; } .page-content{ overflow-y:auto; max-height:100%; font-size:.6em; padding:.6em; text-align:left; } .s-page, .r-page{ background-color: white; color:black; } .page-title { margin: .25em 0; font-weight: 100; font-size: 3em; text-align:center; } .close-button { font-size: 1.5em; width: 1em; height: 1em; position: absolute; top: .75em; right: .75em; cursor: pointer; line-height: .8em; text-align: center }لقد ضبطت الموقع الأصلي لكل صفحة من النوع r-page في الفضاء ثلاثي البعد بتدويرها حول محور التراتيب (محور y) بعد ذلك نقل الصفحة بمقدار 5em إلى يسار الشاشة باستخدام الخاصية translateZ (النقل على محور z). ينبغي ألّا ننسى أنّه عند تحويل (نقل – تدوير) عنصر في الفضاء ثلاثي البعد فمن الضروري تحويل نظام الإحداثيات الخاص به بنفس الصورة. الذي نريده الآن هو نقل الصفحة بمقدار 5em إلى يسار الشاشة، ولكن لاحظ أنّنا بدلًا من استخدام translateX استخدمنا translateZ، ويعود سبب ذلك إلى أنّه بعد التحويل الأوّل (الدوران حول محور y) يدور نظام الإحداثيات أيضًا، وهكذا يُشير محور z في هذه الحالة إلى اليسار وليس إلى الأعلى، أمّا محور الفواصل (محور x) فسيشير باتجاه المستخدم. يكون لجميع الصفحات باستثناء النوع s-page نفس موقع البداية في الفضاء ثلاثي البعد. بالنسبة للصفحات من النوع s-page فإنّها تكون بموقع يبعد بما يُعادل -150% يسار الشاشة (واضح أنّها لن تكون مرئية بهذه الحالة)، بحيث أنّها تنزلق لتعود إلى الشاشة عند تفعيل التحريكة الخاصة بها. عند نقر قطعة مرتبطة بصفحة ما، فسيُضاف صنف CSS الموافق بواسطة JavaScript إلى الصفحة، بالنتيجة ستحصل الصفحة على اسم صنف CSS يُعرّف التأثير ثلاثي البعد الواجب تطبيقه عليها. فيما يلي أسماء أصناف CSS التي تُفعّل عملية فتح وإغلاق الصفحات، بالإضافة إلى التحريكات المعرّفة من أجل كل صنف. .openpage{ animation: rotatePageInFromRight 1s cubic-bezier(.66,.04,.36,1.03) 1 normal forwards; } .slidePageLeft{ transform: rotateY(0) translateZ(0); opacity: 1; animation:slidePageLeft .8s ease-out 1 normal forwards; } .slidePageInFromLeft{ animation: slidePageInFromLeft .8s cubic-bezier(.01,1,.22,.99) 1 0.25s normal forwards; } .slidePageBackLeft{ opacity: 1; left: 0; animation: slidePageBackLeft .8s ease-out 1 normal forwards; }لاحظ أنّني أستخدم الخاصية animation بالشكل المختصر. تعود القيمة الأخيرة forward ضمن الخاصية animation إلى الخاصيّة الفرعية animation-fill-mode، وهذه القيمة ضرورية لها، وإلّا ستعود الصفحة إلى حالتها الابتدائية (المغلقة) فور انتهاء التحريكة التي ستُظهر الصفحة. إذًا لكي نُبقي الصفحة مفتوحة، ولكي نكون قادرين على إنشاء تحريكات متلاحقة، يجب على العنصر أن يبقى مُحتفظًا بحالته النهائية المعرّفة ضمن تحركية ما، ومن هذه "الحالة النهائية" يبدأ عمل التحريكة التالية، وهكذا. فيما يلي التحريكات لأصناف CSS المطبّقة على الصفحات. @keyframes rotatePageInFromRight{ 0% {transform:rotateY(-90deg) translateZ(5em);opacity:0} 30% {opacity:1} 100% {transform: rotateY(0deg) translateZ(0) ; opacity:1} } @keyframes slidePageLeft{ 0% {left:0; transform: rotateY(0deg) translateZ(0) ; opacity:1} 70% {opacity:1;} 100% {opacity:0; left:-150%; transform: rotateY(0deg)} } @keyframes slidePageInFromLeft{ 0% {opacity:0; } 30% {opacity:1} 100% {opacity:1; left:0;} } @keyframes slidePageBackLeft{ 0% {opacity:1; left:0; transform: scale(0.95);} 10% {transform: scale(0.9);} 70% {opacity:1;} 100% {opacity:0; left:-150%;} }أخيرًا وليس آخرًا، سنُنسّق قطع لوح البداية ونُعرّف الانتقالات والتحريكات المطبّقة عليها عند تحريك مؤشّر الفأرة فوقها. لاحظ أنّ التنسيقات العامّة تُعرّف حجم القطع. .tile{ float: left; margin: 0 auto 1%; color: white; font-size: 1.3em; text-align: center; height: 8em; font-weight: 300; overflow: hidden; cursor: pointer; background-color: #fff; color: #333; position:relative; transition: background-color 0.2s ease-out } .tile-2xbig{ height:16.15em; width:100%; } .tile-big { width: 100% } .tile-small { width: 49%; margin-right: 2% } .tile-small.last { margin-right: 0 }سيحتوي زوج من القطع على صورة مع عنوان لها، هاتان القطعتان ستحصلان على الصنف fig-tile وذلك لتمييز نوعهما في شيفرة JavaScript التي سنراها لاحقًا. سنحصل على الألوان المستخدمة من أجل النص والخلفية لصفحة ما من الألوان المستخدمة في العنوان، لذلك لا تنسى أن تُعرّفهم. بالنسبة للعنوان إمّا أن يكون ثابتًا أو أن يُعطي شعورًا بالانزلاق عندما يتحرك فوقه مؤشّر الفأرة: .tile-caption{ position:absolute; z-index:1; background-color: #455962; color:#fff; font-size:1em; padding:1em; text-align: left; } .caption-bottom{ left:0; bottom:0; right:0; height:40%; } .caption-left{ left:-100%; top:0; bottom:0; width:40%; transition: left .3s linear; } .tile:hover .caption-left{ left:0; }بالنسبة للقطع النظامية regular tiles التي لا تملك أي نوع من التحريك، فستغيّر لون خلفيّتها ولون النص عند تحريك الفأرة فوقها. لكي نتأكّد من أنّ النص مُوسّط عموديًا vertically centered في كل قطعة، سنضع في كل قطعة عنصر div يحوي بدوره عنصر فقرة (العنصر <p>) يحوي النص. سنستخدم القيمة table-cell للخاصية display وذلك لتوسيط النص عموديًا ضمن الفقرة: .tile div{ position:absolute; top:0; left:0; right:0; bottom:0; width:100%; height:100%; text-align:center; display:table; padding:0 1em; transition: all .3s ease; } .tile div p{ display:table-cell; vertical-align:middle; }سنترك الحديث عن أنماط التنسيق العامّة للقطع بهدف الاختصار، ولكن ينبغي علينا التأكّد من أنّنا سنعيّن لون النص والخلفية لجميع القطع، حتى تلك التي ستُغطّى بصورة، لأنّ هذه الألوان التي سنحصل عليها باستخدام JavaScript ستُستخدَم لضبط الألوان في الصفحة المرتبطة بها كما أشرنا قبل قليل. دعونا الآن نتحدّث عن التحريكات والانتقالات التي تحدث على قطعة ما. ستحتوي القطع المزوّدة بنص منزلق على عنصري div، سيبدو كل عنصر div كوجه أو كتلة منفصلة داخل القطعة. سيكون تموضعًا عنصريًا div مطلقًا positioned absolutely وسيتحرّكان عند تحرّك الفأرة فوقهما وذلك وفقًا لاتجاه الانزلاق المطلوب. فلكي ينزلق نص القطعة إلى الأعلى عندما يحوم مؤشّر الفأرة فوقه سنطبّق الصنف slideTextUp: .slideTextUp div:nth-child(2){ top:100%; } .slideTextUp:hover div{ transform: translateY(-100%); } .tile-1 p{ font-size:1.3em; }وبشكل مماثل ولكي ينزلق نص القطعة إلى اليسار وإلى اليمين سنطبّق الصنفين slideTextLeft و slideTextRight على الترتيب. .slideTextRight div:first-child{ left:-100%; } .slideTextRight:hover div{ transform: translateX(100%); } .slideTextLeft div:nth-child(2){ left:100%; } .slideTextLeft:hover div{ transform: translateX(-100%); }أمّا بالنسبة لزوج القطع التي ستنقلب، فسيكون لهما تأثير مختلف عندما يحوم مؤشّر الفأرة فوقهما، فهما يدوران ليُظهران الوجه الخلفي. يُعتبر هذا التأثير نوعًا بسيطًا جدًا من تأثير "انقلاب البطاقة" card flip. لن نخوض في تفاصيل هذا التأثير. لإنجاز هذا التأثير، سنطبّق الصنف rotate3d إلى القطعة التي نريد أن تنقلب. بالنسبة للقطعة التي نريد أن تنقلب عموديًّا، سنطبّق الصنف rotate3dy، أمّا بالنسبة للانقلاب الأفقي سنطبّق الصنف rotate3dx (مع الانتباه إلى وجوب وجود الصنف rotate3d في كلتا الحالتين). انظر إلى تنسيقات CSS التالية: .rotate3d{ perspective: 800px; overflow: visible; } .faces{ transform-style: preserve-3d; transition: transform 1s; } .faces div { display: block; position: absolute; top:0; left:0; right:0; bottom:0; width: 100%; height: 100%; backface-visibility: hidden; }لاحظ بأنّه عند تحريك مؤشّر الفأرة فوقهما بالتتالي، فسيظهر وجه أحدهما في حين ستظهر خلفية الآخر بنفس الوقت. .rotate3dY .back{ transform: rotateY( 180deg ); } .rotate3dX .back{ transform: rotateX( 180deg ); }وعندما يحوم مؤشّر الفأرة فوق القطعة فإنّ أي عنصر div يخضع للصنف faces. سيُدوّر ليُظهر وجهه الخلفي: .rotate3dY:hover .faces:hover{ transform: rotateY( 180deg ); } .rotate3dX:hover .faces:hover{ transform: rotateX( 180deg ); } لتنسيق القطع في الدوران ثلاثي البعد، ينبغي الانتباه إلى ضبط لوني الخلفية والنص للوجه الأمامي (ذو الصنف front.) بحيث يمكن الحصول على هذين اللونين واستخدمهما لاحقًا في الصفحة المتربطة بالقطعة عند فتحها. لنعرّف الآن تنسيقات تفاعلية للوح Dashboard. ستكون أعمدة اللوح ذات عرض كامل على الشاشات الصغيرة في البداية (تذكّر أنّنا نراعي متطلبات تصميم الأجهزة المحمولة أولًا mobile-first)، في حين أنّ هذه الأعمدة ستكون بجانب بعضها البعض في الشاشات الكبيرة. .col1, .col2, .col3 { width: 99%; margin: 1em auto } @media screen and (min-width: 43.75em) { .col1, .col2, .col3 { float: left; margin-right: 1%; width: 49% } .page-title{ font-size:2.5em; } .page-content{ font-size:1em; } .close-button{ font-size:2em; } } @media screen and (min-width: 64em) { .col1, .col2, .col3 { float: left; margin-right: .5%; width: 31% } .col3 { margin-right: 0 } .col1 { margin-left: 2em } .page-title{ font-size:3.5em; } } جافا سكريبت JavaScriptستُعالَج جميع أحداث النقر عن طريق JavaScript. سنستخدم مكتبة jQuery لهذه الغاية، وسنضبط معالج حدث event handler النقر لكل قطعة على لوح البداية، فعندما ينقر المستخدم على قطعة ما، يعمل معالج حدث النقر الموافق على الحصول على اسم ونوع الصفحة المرتبطة بهذه القطعة وذلك من السمتين data-page-name و data-page-type على الترتيب، حيث سنستخدم هذه المعلومات لفتح الصفحة المطلوبة. أمّا عند إغلاق الصفحة عند النقر زر الإغلاق لها، فسيعمل معالج حدث النقر لهذا الزر على تطبيق أسماء الأصناف المناسبة لإغلاق الصفحة. بالإضافة لذلك، ولكي نُكسِب كل صفحة لون خلفية ولون نص مماثل لتلك التي للقطعة المرتبطة بها، فإنّنا سنطوف بدايةً على جميع القطع، ونحصل على ألوانها، ثمّ نُطبّق هذه الألوان على الصفحات المرتبطة معها. في حال كان لقطعة ما الصنف rotate3d، فإنّنا سنبحث عن لون الخلفية لوجه face القطعة، ومن ثمّ نطبّق هذا اللون على الصفحة المرتبطة معها. function(){ $('.tile').each(function(){ var $this= $(this), page = $this.data('page-name'), bgcolor = $this.css('background-color'), textColor = $this.css('color'); if($this.hasClass('rotate3d')) { frontface = $this.find('.front'); bgcolor = frontface.css('background-color'); textColor = frontface.css('color'); } if($this.hasClass('fig-tile')) { caption = $this.find('figcaption'); bgcolor = caption.css('background-color'); textColor = caption.css('color'); } $this.on('click',function(){ $('.'+page).css({'background-color': bgcolor, 'color': textColor}) .find('.close-button').css({'background-color': textColor, 'color': bgcolor}); }); }); function showDashBoard(){ for(var i = 1; i <= 3; i++) { $('.col'+i).each(function(){ $(this).addClass('fadeInForward-'+i).removeClass('fadeOutback'); }); } } function fadeDashBoard(){ for(var i = 1; i <= 3; i++) { $('.col'+i).addClass('fadeOutback').removeClass('fadeInForward-'+i); } } $('.tile').each(function(){ var $this= $(this), pageType = $this.data('page-type'), page = $this.data('page-name'); $this.on('click',function(){ if(pageType === "s-page"){ fadeDashBoard(); $('.'+page).addClass('slidePageInFromLeft').removeClass('slidePageBackLeft'); } else{ $('.'+page).addClass('openpage'); fadeDashBoard(); } }); }); $('.r-close-button').click(function(){ $(this).parent().addClass('slidePageLeft') .one('webkitAnimationEnd oanimationend msAnimationEnd animationend', function(e) { $(this).removeClass('slidePageLeft').removeClass('openpage'); }); showDashBoard(); }); $('.s-close-button').click(function(){ $(this).parent().removeClass('slidePageInFromLeft').addClass('slidePageBackLeft'); showDashBoard(); }); })();وبهذا نكون قد وصلنا إلى نهاية الدرس. أرجو أن يكون ممتعًا ومفيدًا. بإمكانك استعراض مثال حيّ لهذا الدّرس من هنا. أما الشيفرة المصدرية فهي مُتوفّرة في هذا المُستودع. ترجمة -وبتصرّف- للمقال How to Create Windows-8-like animations with CSS3 and JQuery لصاحبته Sara Soueidan.
  15. وقعت عيني في أحد الأيام على مبدأ جميل لقائمة في أحد المواقع، وكان أحدهم قد قام ببناء شيء شبيه بها ولكني أردت أن أضيف لها تأثيرات إضافية وأجعلها متناسبة مع متصفحات سطح المكتب. لذلك أردت أن أريك في هذا الدرس كيفية القيام بشيء مشابه. سوف نقوم في هذا الدرس ببناء شيء شبيه بهذه المعاينة (أنظر إلى Demo2) بحيث تكون الأيقونة التي تفتح القائمة موجودة في أعلى يسار الشاشة والحد (border) يكون أسمك من جهة اليسار. ملاحظة: ضع في الحسبان أننا سوف نستعمل تأثيرات التنقل (transitions) والحركة (animation) على عناصر زائفة (pseudo-elements) والتي لن تعمل في بعض المتصفحات (مثل Safari وMobile Safari). بنية ملف HTMLسوف تحتوي بنية HTML الخاصة بالقائمة على عنصر nav وعلى عنصر a وأيضًا على عنصر ul يوجد بداخله مجموعة من عناصر li وبداخل كل عنصر من هذه العناصر يوجد أيقونة: <nav id="bt-menu" class="bt-menu"> <a href="#" class="bt-menu-trigger"><span>Menu</span></a> <ul> <li><a href="#" class="bt-icon icon-zoom">Zoom</a></li> <li><a href="#" class="bt-icon icon-refresh">Refresh</a></li> <li><a href="#" class="bt-icon icon-lock">Lock</a></li> <li><a href="#" class="bt-icon icon-speaker">Sound</a></li> <li><a href="#" class="bt-icon icon-star">Favorite</a></li> </ul> </nav>لنبدأ الآن بتنسيق العناصر باستخدام CSS. تنسيقات CSSملاحظة: التنسيقات التي سوف نقوم بكتابتها لن تحتوي على أي بادئات للمتصفحات (vendor prefixies) ولكنك سوف تجدها في الملفات المصدرية لهذا الدرس. سوف نقوم في البداية بتطبيق الخاصية box-sizing: border-box على جميع العناصر: *, *:after, *::before { box-sizing: border-box; }ودعنا نقوم أيضًا بإعطاء بعض التنسيقات لجسم الصفحة (العنصر body) والحاوي الرئيسي: body { background: #04a466; } .container { padding: 80px; }سوف تساعد خاصية padding: 80px على توفير بعض المساحة حول المحتوى حتى نضمن وجود بعض المساحة عندما تظهر الحدود (border). سوف تكون القائمة الرئيسية متموضعة بشكل ثابت في الصفحة (باستخدام position: fixed) وسوف تكون الحدود دائمًا موجوة حول مجال الرؤية (viewport). سوف نستخدم تنسيقات مبدئية للحدود والتي سوف تتحول إلى حدود أكبر عند النقر على أيقونة القائمة. لاحظ أننا جعلنا الارتفاع يساوي صفر (height: 0) وذلك حتى نضمن بأنّ القائمة لا تُغطّي أي شيء قبل ظهورها على الشاشة، كما أنّه سيكون هناك تأخير بمقدار 0.3s بالنسبة للارتفاع عندما نقوم بإغلاق القائمة: .bt-menu { position: fixed; top: 0; left: 0; width: 100%; height: 0; border-width: 0px; border-style: solid; border-color: #333; background-color: rgba(0,0,0,0); transition: border-width 0.3s, background-color 0.3s, height 0s 0.3s; }عندما نقوم بفتح القائمة فإننا نريد أن نجعل الارتفاع يساوي 100% (ولكننا لن نستخدم الخاصية transition) وسوف نجعل الحدود تساوي 90px على الجهة اليسرى و30px على الجهات الأخرى، كما أنّ لون الخلفية سوف يكون شبه شفاف وذلك باستخدام RGBA: .bt-menu.bt-menu-open { height: 100%; border-width: 30px 30px 30px 90px; background-color: rgba(0,0,0,0.3); transition: border-width 0.3s, background-color 0.3s; }سوف نستعمل الآن خدعة بسيطة بحيث سوف نقوم بإضافة عنصر باستخدام الجافاسكربت ليعمل وكأنّه حاوٍ يغطي كافة الصفحة باستثناء الحدود، وهذا سوف يسمح لنا بأن نعرف أين ننقر حتى نقوم بإغلاق القائمة فنحن لا نريد للقائمة أن تغلق عندما ننقر على الحدود وإنما فقط عند النقر على المساحة الأخرى. .bt-overlay { position: absolute; width: 100%; }وعندما نقوم بفتح القائمة فإنّ هذا العنصر سوف يكون بارتفاع كامل (height: 100%): .bt-menu-open .bt-overlay { height: 100%; }لنقم الآن بتنسيق الأيقونة التي تفتح القائمة عند النقر عليها. سوف نعطيها تموضعًا ثابتًا (position: fixed) وسوف نجعلها تظهر في الجزء العلوي من الجهة اليسار للصفحة: .bt-menu-trigger { position: fixed; top: 15px; left: 20px; display: block; width: 50px; height: 50px; cursor: pointer; }سوف يعمل العنصر a كحاوٍ والعنصر span سيكون الخط المتوسط في أيقونة الهامبرجر (تم تسميتها بهذا الاسم لأنّ شكلها يشبه سندويشة الهامبرجر). لذلك سوف نقوم بموضعة العنصر span في الوسط وذلك بإعطائه الخاصية top: 50% والخاصية margin-top: -2px (هذه خدعة قديمة بحيث نقوم بإعطاء العنصر قيمة margin سالبة بنصف ارتفاع العنصر حتى نجعله يتوسط كما نريد): .bt-menu-trigger span { position: absolute; top: 50%; left: 0; display: block; width: 100%; height: 4px; margin-top: -2px; background-color: #fff; font-size: 0px; user-select: none; transition: background-color 0.3s; }وعند فتح القائمة سوف يتغير شكل الأيقونة التي تفتح القائمة وتغلقها إلى حرف "X"، بحيث سوف نستعمل العناصر الزائفة لإنشاء الخطين المتقاطعين على شكل "X" وسوف نقوم بإخفاء الخط الذي في الوسط (والذي قلنا بأنّه هو نفسه العنصر span): .bt-menu-open .bt-menu-trigger span { background-color: transparent; }لنقم الآن بإنشاء الخطين المتقاطعين كما قلنا باستخدام العناصر الزائفة، بحيث سوف نعطيها الخاصية position: absolute وسوف يكون ارتفاعها بنفس ارتفاع العنصر الذي يحتويها (العنصر span في هذه الحالة) وذلك عن طريق إعطائها الخاصية height: 100%: bt-menu-trigger span:before, .bt-menu-trigger span:after { position: absolute; left: 0; width: 100%; height: 100%; background: #fff; content: ''; transition: transform 0.3s; }وسوف نستخدم الخاصية translateY لموضعتها بشكل صحيح: .bt-menu-trigger span:before { transform: translateY(-250%); } .bt-menu-trigger span:after { transform: translateY(250%); } سوف ينتج الشكل "X" عندما نقوم بفتح القائمة وذلك عن طريق الخاصية (translateY(0 وعن طريق تدوير العناصر الزائفة باستخدام الخاصية (rotate(45deg: .bt-menu-open .bt-menu-trigger span:before { transform: translateY(0) rotate(45deg); } .bt-menu-open .bt-menu-trigger span:after { transform: translateY(0) rotate(-45deg); }كما أنّ العنصر ul الذي سوف يحتوي على الأيقونات سوف يتم موضعته بشكل ثابت (باستخدام position: fixed) وإلى يسار الشاشة: .bt-menu ul { position: fixed; top: 75px; left: 0; margin: 0; padding: 0; width: 90px; list-style: none; backface-visibility: hidden; }لنقم الآن بإعطاء العناصر li و a الخاصية display: block ونجعلها بعرض كامل باستخدام الخاصية width: 100%: .bt-menu ul li, .bt-menu ul li a { display: block; width: 100%; text-align: center; }كل عنصر li سوف يكون مخفيًا بشكل مبدئي وبشفافية منعدمة (opacity: 0)، كما أنّ التنقل الرجعي (backward transition) لخاصية visibility سوف يتم تأخيره حتى تنتهي خاصية التنقل الخاصة بالخاصيتين transform و opacity: .bt-menu ul li { padding: 16px 0; opacity: 0; visibility: hidden; transition: transform 0.3s, opacity 0.2s, visibility 0s 0.3s; }سوف نقوم الآن بتحويل جميع عناصر li بشكل مختلف عن بعضها بحيث تكون جميعها موجودة في الوسط وإلى اليسار إلى أن تختفي (وذلك باستعمال القيمة -100% على المحور العمودي): .bt-menu ul li:first-child { transform: translate3d(-100%,200%,0); } .bt-menu ul li:nth-child(2) { transform: translate3d(-100%,100%,0); } .bt-menu ul li:nth-child(3) { transform: translate3d(-100%,0,0); } .bt-menu ul li:nth-child(4) { transform: translate3d(-100%,-100%,0); } .bt-menu ul li:nth-child(5) { transform: translate3d(-100%,-200%,0); }عند فتح القائمة سوف تظهر العناصر li بشكل فوري لأننا لم نقم بإعطائها خاصية transition. وسوف يتحركوا أيضًا إلى مواقعهم الرئيسية وذلك عن طريق استخدام الخاصية (transform: translate3d(0,0,0: .bt-menu.bt-menu-open ul li { visibility: visible; opacity: 1; transition: transform 0.3s, opacity 0.3s; transform: translate3d(0,0,0); }لنقم الآن بتنسيق عناصر a. سوف نستخدم خط أيقوني (icon font) ونضيف مصدر الخط وفئات الأيقونات (icon classes) الموجودة في ملف CSS آخر والذي توفره خدمة مثل Fontastic أو IcoMoon app. سوف نقوم بإخفاء النص الموجود في العناصر وذلك باستعمال الخاصية font-size: 0px ونجعل اللون شفاف باستخدام color: transparent: .bt-menu ul li a { display: block; outline: none; color: transparent; text-decoration: none; font-size: 0px; }وحتى نجعل الأيقونات تظهر (لأننا قمنا بإخفائها عن طريق font-size: 0 و color:transparent) فإننا سوف نُعطي العناصر الزائفة الخاصية font-size: 48px وcolor: #04a466. لاحظ أننا استعملنا "px" بدل "em" وذلك لأننا أعطينا العنصر الرئيسي القيمة font-size: 0 وبالتالي فإنّ "em" لن تعمل هنا: .bt-menu ul li a:before { color: #04a466; font-size: 48px; transition: color 0.2s; }وعندما يقوم المستخدم بوضع مؤشر الفأرة فوق العنصر (hover) فإننا نريد أن يكون لون الخط أبيضًا: .bt-menu ul li a:hover:before, .bt-menu ul li a:focus:before { color: #fff; }وأخيرًا وليس آخرًا، نريد أن تظهر الأيقونات بحجم أصغر في شاشات الهواتف المحمولة: @media screen and (max-height: 31.125em) { .bt-menu ul li a:before { font-size: 32px; } }هذا كان كل ما يتعلق بتنسيقات CSS. لننتقل الآن إلى الجافاسكربت. بعض الجافاسكربتما نريد فعله بالجافاسكربت بسيط ومباشر، ما نريده هو أنّه عند النقر على أيقونة القائمة فإنّه يتم إضافة/إزالة الفئة (class) التي تحمل الاسم "bt-menu-open" والفئة "bt-menu-close على العنصر nav (إضافة الفئة "bt-menu-close" هي فقط ضرورية إذا كنت سوف تستخدم التحريك (animation) للتأثير الخاص بأيقونة القائمة، تمامًا كما فعلنا في Demo1. وهذا سوف يسمح لنا بتشغيل التحريك الرجعي عندما نقوم بإغلاق القائمة). عندما نقوم بالنقر على عنصر الـoverlay الذي تحدثنا عنه سابقًا نريد أن يتم إغلاق القائمة. وسوف نقوم أيضًا بإضافة بعض الدعم للأجهزة التي تعمل باللمس: (function() { // http://stackoverflow.com/a/11381730/989439 function mobilecheck() { var check = false; (function(a) {if(/(android|ipad|playbook|silk|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4)))check = true})(navigator.userAgent||navigator.vendor||window.opera); return check; } function init() { var menu = document.getElementById( 'bt-menu' ), trigger = menu.querySelector( 'a.bt-menu-trigger' ), // event type (if mobile, use touch events) eventtype = mobilecheck() ? 'touchstart' : 'click', resetMenu = function() { classie.remove( menu, 'bt-menu-open' ); classie.add( menu, 'bt-menu-close' ); }, closeClickFn = function( ev ) { resetMenu(); overlay.removeEventListener( eventtype, closeClickFn ); }; var overlay = document.createElement('div'); overlay.className = 'bt-overlay'; menu.appendChild( overlay ); trigger.addEventListener( eventtype, function( ev ) { ev.stopPropagation(); ev.preventDefault(); if( classie.has( menu, 'bt-menu-open' ) ) { resetMenu(); } else { classie.remove( menu, 'bt-menu-close' ); classie.add( menu, 'bt-menu-open' ); overlay.addEventListener( eventtype, closeClickFn ); } }); } init(); })();خاتمةهذا كان كل شيء. أتمنى أن تكون قد استمتعت بهذا الدرس ووجدته مفيدًا وعمليًا، وتأكد بأن تلقي نظرة على جميع المعاينات (demos) فالمعاينة الأخيرة يوجد بها مبدأ لمشغّل فيديو يأخذ كامل الشاشة. ترجمة -وبتصرّف- للمقال Animated Border Menus لصاحبته Mary Lou.
  16. في هذا المقال القصير سوف نصنع تنبيها مؤقتا بسيطا عبر CSS animations. ما سنفعله بالتحديد هو إظهار تنبيه بسيط أو عبارة ما أسفل الشاشة لمدة معينة، ثم إخفائها. وسوف سنعمل شريط تقدم (progress bar) لنعرف كم تبقى من الوقت ليختفي التنبيه. ستكون تنبيهات هذا الدرس من الشكل التالي: بالنسبة للهيكلة فسوف نستخدم div يحتوي على الرسالة وبداخله div آخر من أجل شريط التقدم: <div class="tn-box tn-box-color-1"> <p>Your settings have been saved successfully!</p> <div class="tn-progress"></div> </div>سيملك التنبيه tn-box. و tn-box-color-1. من أجل تحديد اللون، سوف نثبت الصندوق أسفل النافذة حتى يرتفع عندما يظهر: .tn-box { width: 360px; position: fixed; bottom: 20px; left: 20px; padding: 25px 15px; text-align: right; border-radius: 5px; box-shadow: 0 1px 1px rgba(0,0,0,0.1), inset 0 1px 0 rgba(255,255,255,0.6); opacity: 0; cursor: default; display: none; transform: translateY(30px) } .tn-box-color-1{ background: #ffe691; border: 1px solid #f6db7b; }أما بالنسبة لشريط التقدم فسنعطيه التالي: .tn-progress { width: 0; height: 4px; background: rgba(255,255,255,0.3); position: absolute; bottom: 5px; right: 2%; border-radius: 3px; box-shadow: inset 0 1px 1px rgba(0,0,0,0.05), 0 -1px 0 rgba(255,255,255,0.6); }في البداية، سيكون عرض شريط التقدم 0. في هذا المثال، أنا أستخدم checkbox من أجل إطلاق animation عندما يتم الضغط عليه: <input type="checkbox" class="fire-check"> <section> <div class="tn-box tn-box-color-1"> <p>شريط التقدم الجميل!</p> <div class="tn-progress"></div> </div> </section>الزر يسبق صندوق التنبيهات لذا نستطيع استخدام محدد ~ من أجل تحديد العنصر الذي يأتي بعده. وإذا أردت أن تتحكم بالأمر عبر جافاسكربت (عبر إضافة tn-box-active. )، فاستخدم التالي: .tn-box.tn-box-active { display: block; animation: fadeOut 5s cubic-bezier(0.4, 0, 0.2, 1) forwards; } .tn-box.tn-box-active .tn-progress { animation: runProgress 4s linear forwards 0.5s; }أما بالنسبة للحركية (animation) فهي كالتالي: @keyframes fadeOut { 0% { opacity: 0; } 10% { opacity: 1; transform: translateY(0px);} 90% { opacity: 1; transform: translateY(0px);} 99% { opacity: 0; transform: translateY(30px);} 100% { opacity: 0; } } @keyframes runProgress { 0% { width: 0%; background: rgba(255,255,255,0.3); } 100% { width: 96%; background: rgba(255,255,255,1); } }ما ستقوم به الـحركية (animation) هو إظهار الصندوق (عبر رفعه ورفع درجة الشفافية) ثم تكبير عرض شريط التقدم. حددنا عرض شريط التقدم إلى 96% (لأنه يبعد عن يمين الصندوق بـ 2% لذا نريده أن يتوقف قبل 2% من اليسار أيضا). مثال حيSee the Pen ZbzMWQ by Hsoub Academy (@HsoubAcademy) on CodePen. ملاحظة: شيء إضافي وجدت أنه من الجميل إضافته هو إيقاف animation عند تمرير المؤشر على الصندوق. ولكن للأسف، الأمر لم ينجح في chrome بينما نجح في فيرفكس. .tn-box:hover, .tn-box:hover .tn-progress{ animation-play-state: paused; }ترجمة -وبتصرف- للمقال: Timed Notifications with CSS Animations لصاحبه Mary Lou. حقوق الصورة البارزة: Designed by Freepik.
×
×
  • أضف...