CSS Infinite 3D Sliders ذكاء بيانات PlatoBlockchain. البحث العمودي. منظمة العفو الدولية.

المتزلجون CSS لانهائي 3D

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

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

سلسلة CSS Sliders

هذا ما نهدف إليه:

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

الآن بعد أن أصبح لدينا صورة مرئية جيدة لكيفية ترتيب الصور ، دعنا نحلل الكود لنرى كيف نصل إلى هناك.

الإعداد الأساسي

نفس HTML مثل باقي أشرطة التمرير التي استخدمناها لأشرطة التمرير الأخرى:

ومرة أخرى ، نستخدم CSS Grid لوضع الصور في مكدس ، واحدة فوق الأخرى:

.gallery {
  display: grid;
}
.gallery > img {
  grid-area: 1 / 1;
  width: 160px;
  aspect-ratio: 1;
  object-fit: cover;
}

الرسوم المتحركة

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

لقد اعتمدنا على CSS transform-origin و animation-delay خصائص هذا المنزلق الأول. يتم تطبيق نفس الرسم المتحرك على جميع عناصر الصورة ، والتي تدور حول نفس النقطة. ثم ، باستخدام تأخيرات مختلفة ، نضع جميع الصور بشكل صحيح حول دائرة كبيرة.

سيكون التنفيذ مختلفًا قليلاً بالنسبة لشريط التمرير ثلاثي الأبعاد الخاص بنا. استخدام transform-origin لن تعمل هنا لأننا نعمل بتقنية ثلاثية الأبعاد ، لذا سنستخدمها transform بدلاً من ذلك لوضع جميع الصور بشكل صحيح ، ثم قم بتدوير الحاوية.

نحن نصل إلى Sass مرة أخرى حتى نتمكن من تكرار عدد الصور وتطبيق تحويلاتنا:

@for $i from 1 to ($n + 1) {
  .gallery > img:nth-child(#{$i}) {
     transform: 
       rotate(#{360*($i - 1) / $n}deg) /* 1 */
       translateY(50% / math.tan(180deg / $n)) /* 2 */ 
       rotateX(90deg); /* 3 */
  }
}

قد تتساءل عن سبب قفزنا مباشرة إلى Sass. بدأنا بعدد ثابت من الصور باستخدام Vanilla CSS في المقالات الأخرى قبل تعميم الكود مع Sass لحساب أي رقم (N) من الصور. حسنًا ، أعتقد أنك حصلت على الفكرة الآن ويمكننا قطع كل أعمال الاكتشاف للوصول إلى التنفيذ الحقيقي.

transform تأخذ الخاصية ثلاث قيم ، والتي أوضحتها هنا:

المتزلجون CSS لانهائي 3D

نقوم أولاً بتدوير جميع الصور فوق بعضها البعض. زاوية الدوران تعتمد على عدد الصور. إلى عن على N من الصور ، لدينا زيادة تساوي 360deg/N. بعدها نحن translate كل الصور بنفس المقدار بطريقة تجعل نقاط مركزها تلتقي على الجانبين.

عرض مجموعة الصور المرتبة بشكل مسطح في دائرة مع وجود خط أحمر يمر عبر النقطة المركزية للصور.
المتزلجون CSS لانهائي 3D

هناك بعض الأشكال الهندسية المملة التي تساعد في شرح كيفية عمل كل هذا ، لكن المسافة تساوي 50%/tan(180deg/N). تعاملنا مع معادلة مماثلة عند عمل شريط التمرير الدائري ( transform-origin: 50% 50%/sin(180deg/N) ).

أخيرًا ، نقوم بتدوير الصور حول المحور السيني بمقدار 90deg للحصول على الترتيب الذي نريده. إليك مقطع فيديو يوضح ما يفعله الدوران الأخير:

الآن كل ما يتعين علينا القيام به هو تدوير الحاوية بأكملها لإنشاء شريط التمرير اللانهائي الخاص بنا.

.gallery {
  transform-style: preserve-3d;
  --_t: perspective(280px) rotateX(-90deg);
  animation: r 12s cubic-bezier(.5, -0.2, .5, 1.2) infinite;
}
@keyframes r {
  0%, 3% {transform: var(--_t) rotate(0deg); }
  @for $i from 1 to $n {
    #{($i/$n)*100 - 2}%, 
    #{($i/$n)*100 + 3}% {
      transform: var(--_t) rotate(#{($i / $n) * -360}deg);
    }  
  }
  98%, 100% { transform: var(--_t) rotate(-360deg); }
}

قد يكون من الصعب فهم هذا الرمز ، لذلك دعونا في الواقع نتراجع قليلاً ونعيد النظر في الرسوم المتحركة التي صنعناها لشريط التمرير الدائري. هذا ما كتبناه في المقال الأول:

.gallery {
  animation: m 12s cubic-bezier(.5, -0.2, .5, 1.2) infinite;
}
@keyframes m {
  0%, 3% { transform: rotate(0); }
  @for $i from 1 to $n {
    #{($i / $n) * 100 - 2}%,
    #{($i / $n) * 100 + 3}% { 
      transform: rotate(#{($i / $n) * -360}deg);
    }  
  }
  98%, 100% { transform: rotate(-360deg); }
}

الإطارات الرئيسية متطابقة تقريبًا. لدينا نفس قيم النسبة المئوية ، ونفس الحلقة ، ونفس الدوران.

لماذا كلاهما نفس الشيء؟ لأن منطقهم هو نفسه. في كلتا الحالتين ، يتم ترتيب الصور حول شكل دائري ونحتاج إلى تدوير كل شيء لإظهار كل صورة. هكذا تمكنت من نسخ الإطارات الرئيسية من شريط التمرير الدائري واستخدام نفس الرمز لشريط التمرير ثلاثي الأبعاد. الاختلاف الوحيد هو أننا نحتاج إلى تدوير الحاوية -90deg على طول المحور السيني لرؤية الصور حيث قمنا بالفعل بتدويرها بمقدار 90deg على نفس المحور. ثم نضيف لمسة من perspective للحصول على التأثير ثلاثي الأبعاد.

هذا هو! تم الانتهاء من شريط التمرير الخاص بنا. هنا هو العرض الكامل مرة أخرى. كل ما عليك فعله هو إضافة العديد من الصور كما تريد وتحديث متغير واحد لبدء العمل.

شريط التمرير العمودي ثلاثي الأبعاد

نظرًا لأننا نلعب في الفضاء ثلاثي الأبعاد ، فلماذا لا ننشئ نسخة عمودية من شريط التمرير السابق؟ يدور الأخير على طول المحور z ، لكن يمكننا أيضًا التحرك على طول المحور x إذا أردنا ذلك.

إذا قارنت الكود لكلا الإصدارين من شريط التمرير هذا ، فقد لا تكتشف الفرق فورًا لأنه حرف واحد فقط! أنا محل rotate() مع rotateX() داخل الإطارات الرئيسية والصورة transform. هذا هو!

تجدر الإشارة إلى أن rotate() ما يعادل rotateZ()، لذلك عن طريق تغيير المحور من Z إلى X نقوم بتحويل شريط التمرير من الإصدار الأفقي إلى الإصدار الرأسي.

منزلق مكعب

لا يمكننا التحدث عن 3D في CSS بدون نتحدث عن المكعبات. ونعم ، هذا يعني أننا سنصنع نسخة أخرى من شريط التمرير.

الفكرة وراء هذا الإصدار من شريط التمرير هي إنشاء شكل مكعب فعلي مع الصور وتدوير الشيء بالكامل حول المحور المختلف. نظرًا لأنه مكعب ، فإننا نتعامل مع ستة وجوه. سنستخدم ست صور ، واحدة لكل وجه من وجوه المكعب. لذا ، لا يوجد Sass ولكن العودة إلى Vanilla CSS.

هذه الرسوم المتحركة ساحقة قليلاً ، أليس كذلك؟ من أين تبدأ؟

لدينا ستة أوجه ، لذا نحتاج إلى إجراء ست دورات على الأقل حتى تحصل كل صورة على دور. حسنًا ، في الواقع ، نحتاج إلى خمس دورات - آخرها يعيدنا إلى وجه الصورة الأول. إذا أخذت مكعب روبيك - أو أي شيء آخر على شكل مكعب مثل النرد - وقمت بتدويره بيدك ، فستكون لديك فكرة جيدة عما نفعله.

.gallery {
  --s: 250px; /* the size */

  transform-style: preserve-3d;
  --_p: perspective(calc(2.5*var(--s)));
  animation: r 9s infinite cubic-bezier(.5, -0.5, .5, 1.5);
}

@keyframes r {
  0%, 3%   { transform: var(--_p); }
  14%, 19% { transform: var(--_p) rotateX(90deg); }
  31%, 36% { transform: var(--_p) rotateX(90deg) rotateZ(90deg); }
  47%, 52% { transform: var(--_p) rotateX(90deg) rotateZ(90deg) rotateY(-90deg); }
  64%, 69% { transform: var(--_p) rotateX(90deg) rotateZ(90deg) rotateY(-90deg) rotateX(90deg); }
  81%, 86% { transform: var(--_p) rotateX(90deg) rotateZ(90deg) rotateY(-90deg) rotateX(90deg) rotateZ(90deg); }
  97%, 100%{ transform: var(--_p) rotateX(90deg) rotateZ(90deg) rotateY(-90deg) rotateX(90deg) rotateZ(90deg) rotateY(-90deg); }
}

transform تبدأ الخاصية بصفر دوران ، وفي كل حالة ، نلحق دورانًا جديدًا على محور معين حتى نصل إلى ست دورات. ثم نعود إلى الصورة الأولى.

دعونا لا ننسى وضع صورنا. يتم تطبيق كل واحدة على وجه المكعب باستخدام transform:

.gallery img {
  grid-area: 1 / 1;
  width: var(--s);
  aspect-ratio: 1;
  object-fit: cover;
  transform: var(--_t,) translateZ(calc(var(--s) / 2));
}
.gallery img:nth-child(2) { --_t: rotateX(-90deg); }
.gallery img:nth-child(3) { --_t: rotateY( 90deg) rotate(-90deg); }
.gallery img:nth-child(4) { --_t: rotateX(180deg) rotate( 90deg); }
.gallery img:nth-child(5) { --_t: rotateX( 90deg) rotate( 90deg); }
.gallery img:nth-child(6) { --_t: rotateY(-90deg); }

ربما تعتقد أن هناك منطقًا غريبًا معقدًا وراء القيم التي أستخدمها هناك ، أليس كذلك؟ حسننا، لا. كل ما فعلته هو فتح DevTools واللعب بقيم دوران مختلفة لكل صورة حتى فهمتها بشكل صحيح. قد يبدو الأمر غبيًا ولكنه يعمل - خاصة وأن لدينا عددًا ثابتًا من الصور ولا نبحث عن شيء يدعم N الصور.

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

ما الحيلة مع وجود الفاصلة داخل ملف var()؟ هل هو خطأ مطبعي؟

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

من المواصفات:

ملاحظة: هذا هو ، var(--a,) هي وظيفة صالحة ، مع تحديد أنه إذا كان --a الخاصية المخصصة غير صالحة أو مفقودة ، فإن var()يجب استبداله بشيء.

عشوائية مكعب المنزلق

يمكن أن يكون القليل من العشوائية تحسينًا رائعًا لهذا النوع من الرسوم المتحركة. لذلك ، بدلاً من تدوير المكعب بترتيب تسلسلي ، يمكننا دحرجة النرد إذا جاز التعبير ، وترك المكعب يتدحرج كيفما شاء.

رائع ، أليس كذلك؟ لا أعرف عنك ، لكني أحب هذا الإصدار أكثر! إنه أكثر إثارة للاهتمام والانتقالات مرضية للمشاهدة. وتخيل ماذا؟ يمكنك اللعب بالقيم لإنشاء منزلق مكعب عشوائي خاص بك!

المنطق في الواقع ليس عشوائيًا على الإطلاق - إنه يظهر بهذه الطريقة. أنت تحدد أ transform على كل إطار رئيسي يسمح لك بإظهار وجه واحد و ... حسنًا ، هذا كل شيء حقًا! يمكنك اختيار أي طلب تريده.

@keyframes r {
  0%, 3%   { transform: var(--_p) rotate3d( 0, 0, 0,  0deg); }
  14%,19%  { transform: var(--_p) rotate3d(-1, 1, 0,180deg); }
  31%,36%  { transform: var(--_p) rotate3d( 0,-1, 0, 90deg); }
  47%,52%  { transform: var(--_p) rotate3d( 1, 0, 0, 90deg); }
  64%,69%  { transform: var(--_p) rotate3d( 1, 0, 0,-90deg); }
  81%,86%  { transform: var(--_p) rotate3d( 0, 1, 0, 90deg); }
  97%,100% { transform: var(--_p) rotate3d( 0, 0, 0,  0deg); }
}

أنا باستخدام rotate3d() هذه المرة ولكني ما زلت أعتمد على DevTools للعثور على القيم التي تشعر بأنها "مناسبة" بالنسبة لي. لا تحاول العثور على علاقة بين الإطارات الرئيسية لأنه ببساطة لا توجد علاقة. أقوم بتعريف تحويلات منفصلة ثم أشاهد النتيجة "العشوائية". تأكد من أن الصورة الأولى هي الإطارات الأولى والأخيرة ، على التوالي ، وقم بإظهار صورة مختلفة على كل إطار من الإطارات الأخرى.

لست ملزمًا باستخدام ملف rotate3d() تحويل كما فعلت. يمكنك أيضًا إجراء سلسلة من الدورات المختلفة كما فعلنا في المثال السابق. العب حولها وشاهد ما يمكنك التوصل إليه! سأنتظر منك مشاركة نسختك معي في قسم التعليقات!

اختتام

أتمنى أن تكون قد استمتعت بهذه السلسلة الصغيرة. قمنا ببناء بعض أشرطة التمرير الممتعة (والمضحكة) أثناء تعلم الكثير عن جميع أنواع مفاهيم CSS على طول الطريق - من وضع الشبكة وترتيب التراص ، إلى تأخيرات الرسوم المتحركة والتحولات. حتى أننا لعبنا مع اندفاعة من Sass للدوران عبر مجموعة من العناصر.

وقمنا بكل ذلك باستخدام نفس HTML بالضبط لكل شريط تم إنشاؤه. كم ذلك رائع؟ CSS قوية وقادرة على إنجاز الكثير بدون مساعدة JavaScript.

الطابع الزمني:

اكثر من الخدع المغلق