تأثير الانتقال في مشهد فضائي


عبد اللطيف ايمش

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

الانتقالات أم الحركات

الانتقالات (transitions) رائعة للانتقال بسلاسة من حالة إلى أخرى (والعودة إلى الحالة الأصلية مجددًا) في المتصفح، وقد تبدو أنها بديلٌ أبسط من الحركات (animation) التي تستعمل keyframes و animation، لكن لكلٍ ميزاتها وفوائدها.
فمثلًا، لن تستفيد من الانتقالات إذا كنت تريد حدوث حركة عند تحميل الصفحة، أو إذا أردتَ أن تستمر الحركة طوال الوقت؛ أما إذا كانت لديك حالتين وأردتَ التحريك بينهما بسهولة فستستفيد حينئذٍ من الانتقالات. إذا كنتَ مهتمًا بالفروقات بين الانتقالات والحركات فأنصحك بمراجعة هذه المقالة.
سنبني في هذا الدرس مشهدًا من الفضاء وسنضيف إليه تأثير مرور الفأرة فوقه لعرض بعض المعلومات الإضافية عن الكوكب، وسنفِّكر بحالتَي العناصر وما هي الخاصيات التي سنستخدمها للحصول على انتقال سلس وجميل. يمكنك الاطلاع على المثال الكامل لأخذ فكرة عن ما سنفعله.
 

ضبط الحالتين

أكثر الأمور التي تأخذ وقتًا وجهدًا عند إنشاء الانتقالات هي الحالة الأولية والحالة النهائية للعنصر، فيجب أن نُفكِّر كيف سيبدو العنصر قبل تطبيق الانتقال وماذا يجب أن يتغيّر في مظهره بعد حدوث الانتقال.
عندما أُنشِئ الانتقالات المعقدة نسبيًا فلا أهتم بالحركة نفسها إلى أن يعجبني مظهر العناصر في الحالتين، ومن هذا المنطلق فسنهتم بالخاصيات التي سنستخدمها في حالة 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);
  }
}

هذا هو ناتج هذه المرحلة:

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

نريد أن نظهر معلومات مفيدة حول كوكب الأرض عند مرور الفأرة فوقه، ربما ستساعد هذه المعلومات الفضائيين في معرفة بعض الأمور الأساسية عن كوكبنا قبل أن يزورونا :-) .
علينا قبل ضبط حالة 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 وهذا يعني أنَّ العنصر سيعود إلى حجمه الطبيعي.
هذه هي النتيجة الحالية، مرر الفأرة فوق الكوكب لتشاهد مربع المعلومات.

تطبيق تأثير الانتقال

لقد أنجزنا الأمور الصعبة، وكل ما بقي علينا لنفعل هو إخبار المتصفح كيف سيتنقل بين الحالتين. ولحسن الحظ لن نحتاج إلى كتابة شيفرات طويلة، وإنما يمكن فعل ذلك بخاصية 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;
}

الشيفرة السابقة ستُضيف تأخيرًا إلى كل عنصرٍ من عناصر القائمة، ولأننا استخدمنا المُحدِّد * فيما سبق فهذا يعني أنَّ كل عنصر من هذه العناصر سيُطبَّق عليه تأثير الانتقال، وكل ما علينا تحديده هو زمن التأخير.
هذه هي النتيجة النهائية:

لقد فعلناها! حركة معقدة نسبيًا أنجزناها باستخدام خاصية transition وحيدة.
تعلمنا في هذا الدرس كيف نخطط ونبني مثالًا متكاملًا يستخدم الانتقالات لإنشاء حركات معقدة، وحرصنا أن تكون الانتقالات سلسلة وتبدو بشكلٍ جميل.

الخلاصة

الخدع البسيطة التي نقوم بها عبر الحركات والانتقالات هي التي تجعل موقعنا مميزًا وجميلًا
ترجمة –وبتصرّف– للمقال Transitions in space لصاحبه Donovan Hutchinson



1 شخص أعجب بهذا


تفاعل الأعضاء


شكراً جزيلاً على الشرح ممتاز

1 شخص أعجب بهذا

شارك هذا التعليق


رابط هذا التعليق
شارك على الشبكات الإجتماعية

جميل جدا

1 شخص أعجب بهذا

شارك هذا التعليق


رابط هذا التعليق
شارك على الشبكات الإجتماعية


يجب أن تكون عضوًا لدينا لتتمكّن من التعليق

انشاء حساب جديد

يستغرق التسجيل بضع ثوان فقط


سجّل حسابًا جديدًا

تسجيل الدخول

تملك حسابا مسجّلا بالفعل؟


سجّل دخولك الآن