در آخرین مقاله، ما یک نوار لغزنده کوچک (یا «چرخ فلک» اگر ترجیح می دهید) درست کردیم که در جهت دایره ای می چرخد. این بار میخواهیم تصویری بسازیم که پشتهای از تصاویر پولاروید را ورق بزند.
باحال درسته؟ هنوز به کد نگاه نکنید زیرا چیزهای زیادی برای باز کردن وجود دارد. به من بپیوندید، آیا؟
سری CSS Sliders
تنظیم اولیه
بیشتر HTML و CSS برای این نوار لغزنده شبیه دایرهای است که دفعه قبل ساختیم. در واقع، ما دقیقاً از همان نشانه گذاری استفاده می کنیم:
و این CSS اساسی است که والدین ما را تنظیم می کند .gallery
ظرفی به عنوان یک شبکه که در آن همه تصاویر روی هم چیده می شوند:
.gallery {
display: grid;
width: 220px; /* controls the size */
}
.gallery > img {
grid-area: 1 / 1;
width: 100%;
aspect-ratio: 1;
object-fit: cover;
border: 10px solid #f2f2f2;
box-shadow: 0 0 4px #0007;
}
هیچ چیز پیچیده ای تا اینجا نیست. حتی برای سبک پولاروید مانند برای تصاویر، تمام چیزی که من استفاده می کنم مقداری است border
و box-shadow
. ممکن است بتوانید این کار را بهتر انجام دهید، پس با خیال راحت با آن سبک های تزئینی بازی کنید! ما بیشتر تمرکزمان را روی انیمیشن می گذاریم، که پیچیده ترین قسمت است.
ترفند چیست؟
منطق این نوار لغزنده به ترتیب انباشتن تصاویر متکی است - بنابراین بله، ما قصد داریم با آن بازی کنیم z-index
. همه تصاویر با همین شروع می شوند z-index
مقدار (2
) که به طور منطقی آخرین تصویر را در بالای پشته ایجاد می کند.
آخرین تصویر را می گیریم و آن را به سمت راست می کشیم تا تصویر بعدی در پشته نمایان شود. سپس تصویر را کاهش می دهیم z-index
سپس آن را به داخل عرشه برمیگردانیم. و از آنجایی که z-index
مقدار کمتر از بقیه تصاویر است، به آخرین تصویر در پشته تبدیل می شود.
در اینجا یک نسخه ی نمایشی است که این ترفند را نشان می دهد. تصویر را نگه دارید تا انیمیشن فعال شود:
حال تصور کنید که همان ترفند برای همه تصاویر اعمال می شود. اگر از آن استفاده می کنیم الگوی اینجاست :nth-child()
شبه انتخابگر برای متمایز کردن تصاویر:
- آخرین تصویر را اسلاید می کنیم (
N
). تصویر بعدی قابل مشاهده است (N - 1
). - تصویر بعدی را اسلاید می کنیم (
N - 1
). تصویر بعدی قابل مشاهده است (N - 2
) - تصویر بعدی را اسلاید می کنیم (
N - 2
). تصویر بعدی قابل مشاهده است (N - 3
) - (به همین روند ادامه می دهیم تا به تصویر اول برسیم)
- اولین تصویر را اسلاید می کنیم (
1
). آخرین تصویر (N
) دوباره قابل مشاهده است.
این لغزنده بی نهایت ماست!
تشریح انیمیشن
اگر مطلب قبلی را به خاطر داشته باشید، من برای کنترل هر تصویر فقط یک انیمیشن تعریف کردم و با تاخیر بازی کردم. ما در اینجا همین کار را خواهیم کرد. بیایید ابتدا سعی کنیم تایم لاین انیمیشن خود را تجسم کنیم. ما با سه تصویر شروع می کنیم، سپس آن را برای هر عدد تعمیم می دهیم (N
) از تصاویر.
انیمیشن ما به سه بخش تقسیم می شود: "اسلاید به راست"، "لغزش به چپ" و "حرکت نشو". ما به راحتی می توانیم تاخیر بین هر تصویر را تشخیص دهیم. اگر در نظر بگیریم که تصویر اول در شروع می شود 0s
، و مدت آن برابر است 6s
، سپس دومی در شروع خواهد شد -2s
و سومی در -4s
.
.gallery > img:nth-child(2) { animation-delay: -2s; } /* -1 * 6s / 3 */
.gallery > img:nth-child(3) { animation-delay: -4s; } /* -2 * 6s / 3 */
همچنین میتوانیم ببینیم که قسمت «حرکت نکن» دو سوم کل انیمیشن را میگیرد (2*100%/3
) در حالی که بخش های «slide to right» و «slide to left» یک سوم آن را با هم می گیرند - بنابراین، هر یک برابر است با 100%/6
از کل انیمیشن
میتوانیم فریمهای کلیدی انیمیشن خود را به این صورت بنویسیم:
@keyframes slide {
0% { transform: translateX(0%); }
16.67% { transform: translateX(120%); }
33.34% { transform: translateX(0%); }
100% { transform: translateX(0%); }
}
که 120%
یک مقدار دلخواه است. من به چیزی بزرگتر از آن نیاز داشتم 100%
. تصاویر باید به سمت راست و دور از بقیه تصاویر اسلاید شوند. برای انجام این کار، حداقل باید حرکت کند 100%
از اندازه آن برای همین رفتم 120%
- برای به دست آوردن فضای اضافی
حال باید در نظر بگیریم z-index
. فراموش نکنید که باید تصاویر را به روز کنیم z-index
ارزش بعد از به سمت راست شمع می لغزد و قبل از ما آن را به پایین شمع می کشانیم.
@keyframes slide {
0% { transform: translateX(0%); z-index: 2; }
16.66% { transform: translateX(120%); z-index: 2; }
16.67% { transform: translateX(120%); z-index: 1; } /* we update the z-order here */
33.34% { transform: translateX(0%); z-index: 1; }
100% { transform: translateX(0% ); z-index: 1; }
}
به جای تعریف یک حالت در 16.67%
(100%/6
) نقطه در جدول زمانی، ما دو حالت را در نقاط تقریباً یکسان تعریف می کنیم (16.66%
و 16.67%
) جایی که z-index
قبل از اینکه تصویر را به عرشه برگردانیم، مقدار کاهش می یابد.
وقتی همه اینها را با هم جمع می کنیم چه اتفاقی می افتد:
هوم، به نظر می رسد قسمت کشویی خوب کار می کند، اما ترتیب انباشته شدن همه چیز درهم است! انیمیشن به خوبی شروع می شود زیرا تصویر بالا به سمت عقب حرکت می کند ... اما تصاویر بعدی از این کار پیروی نمی کنند. اگر متوجه شدید، تصویر دوم در دنباله قبل از چشمک زدن تصویر بعدی در بالای پشته به بالای پشته باز می گردد.
ما باید از نزدیک دنبال کنیم z-index
تغییر می کند. در ابتدا، تمام تصاویر هستند z-index: 2
. این بدان معناست که ترتیب انباشته شدن باید از بین برود…
Our eyes 👀 --> 3rd (2) | 2nd (2) | 1st (2)
تصویر سوم را اسلاید می کنیم و آن را به روز می کنیم z-index
برای دریافت این سفارش:
Our eyes 👀 --> 2nd (2) | 1st (2) | 3rd (1)
ما همین کار را با دومی انجام می دهیم:
Our eyes 👀 --> 1st (2) | 3rd (1) | 2nd (1)
و اولی:
Our eyes 👀 --> 3rd (1) | 2nd (1) | 1st (1)
ما این کار را می کنیم و به نظر می رسد همه چیز خوب است. اما در واقعیت، اینطور نیست! هنگامی که تصویر اول به پشت منتقل می شود، تصویر سوم تکرار دیگری را آغاز می کند، به این معنی که به آن باز می گردد z-index: 2
:
Our eyes 👀 --> 3rd (2) | 2nd (1) | 1st (1)
بنابراین، در واقعیت ما هرگز همه تصاویر را در اختیار نداشتیم z-index: 2
اصلا! هنگامی که تصاویر متحرک نیستند (یعنی قسمت «حرکت نکنید» انیمیشن) z-index
is 1
. اگر تصویر سوم را اسلاید کنیم و آن را به روز کنیم z-index
ارزش از 2
به 1
، در اوج باقی خواهد ماند! وقتی همه تصاویر یکسان باشند z-index
، آخرین تصویر در ترتیب منبع - تصویر سوم ما در این مورد - در بالای پشته است. لغزش تصویر سوم به صورت زیر نتیجه می شود:
Our eyes 👀 --> 3rd (1) | 2nd (1) | 1st (1)
تصویر سوم همچنان در بالا است و درست بعد از آن، تصویر دوم را با شروع مجدد انیمیشن آن به بالا منتقل می کنیم. z-index: 2
:
Our eyes 👀 --> 2nd (2) | 3rd (1) | 1st (1)
وقتی آن را بلغزانیم، دریافت می کنیم:
Our eyes 👀 --> 3rd (1) | 2nd (1) | 1st (1)
سپس اولین تصویر به بالای صفحه می پرد:
Our eyes 👀 --> 1st(2) | 3rd (1) | 2nd (1)
باشه من گم شدم پس همه منطق اشتباه است؟
می دانم، گیج کننده است. اما منطق ما کاملاً اشتباه نیست. ما فقط باید کمی انیمیشن را اصلاح کنیم تا همه چیز آنطور که می خواهیم کار کند. ترفند این است که به درستی تنظیم مجدد z-index
.
بیایید وضعیتی را در نظر بگیریم که تصویر سوم در بالا قرار دارد:
Our eyes 👀 --> 3rd (2) | 2nd (1) | 1st (1)
دیدیم که تصویر سوم را لغزانده و آن را تغییر می دهیم z-index
آن را در بالا نگه می دارد. آنچه ما باید انجام دهیم این است که به روز رسانی z-index
از تصویر دوم بنابراین، قبل از اینکه تصویر سوم را از عرشه دور کنیم، آن را به روز می کنیم z-index
از تصویر دوم به 2
.
به عبارت دیگر، ما آن را ریست می کنیم z-index
تصویر دوم قبل از پایان انیمیشن.
نماد سبز سبز نشان دهنده افزایش است z-index
به 2
، و نماد قرمز منهای مربوط به z-index: 1
. تصویر دوم با شروع می شود z-index: 2
، سپس آن را به روز می کنیم 1
وقتی از عرشه دور می شود. اما قبل از اینکه اولین تصویر از عرشه دور شود، آن را تغییر می دهیم z-index
از تصویر دوم برگشت به 2
. با این کار مطمئن می شوید که هر دو تصویر یکسان هستند z-index
، اما با این حال، سومی در بالا باقی می ماند زیرا بعداً در DOM ظاهر می شود. اما بعد از اسلایدهای تصویر سوم و آن z-index
به روز می شود، به پایین حرکت می کند.
این دو سوم از انیمیشن است، بنابراین بیایید فریم های کلیدی خود را بر این اساس به روز کنیم:
@keyframes slide {
0% { transform: translateX(0%); z-index: 2; }
16.66% { transform: translateX(120%); z-index: 2; }
16.67% { transform: translateX(120%); z-index: 1; } /* we update the z-order here */
33.34% { transform: translateX(0%); z-index: 1; }
66.33% { transform: translateX(0%); z-index: 1; }
66.34% { transform: translateX(0%); z-index: 2; } /* and also here */
100% { transform: translateX(0%); z-index: 2; }
}
کمی بهتر است، اما هنوز نه کاملا آنجا. یه مسئله دیگه هم هست…
اوه نه، این هرگز تمام نمی شود!
نگران نباشید، ما قرار نیست دوباره فریم های کلیدی را تغییر دهیم زیرا این مشکل تنها زمانی رخ می دهد که آخرین تصویر درگیر باشد. میتوانیم یک انیمیشن فریم کلیدی «ویژه» بهطور خاص برای آخرین تصویر بسازیم تا همه چیز را اصلاح کنیم.
وقتی اولین تصویر در بالای صفحه باشد، وضعیت زیر را داریم:
Our eyes 👀 --> 1st (2) | 3rd (1) | 2nd (1)
با توجه به تنظیمات قبلی که انجام دادیم، تصویر سوم قبل از اسلاید تصویر اول به بالا میپرد. فقط در این شرایط اتفاق می افتد زیرا تصویر بعدی که بعد از اولین تصویر حرکت می کند تصویر است آخر تصویری که در DOM مرتبه بالاتری دارد. بقیه تصاویر خوب هستند زیرا ما داریم N
، و سپس N - 1
، سپس ما از 3
به 2
و 2
به 1
... اما بعد از آن می رویم 1
به N
.
برای جلوگیری از آن، از فریم های کلیدی زیر برای آخرین تصویر استفاده می کنیم:
@keyframes slide-last {
0% { transform: translateX(0%); z-index: 2;}
16.66% { transform: translateX(120%); z-index: 2; }
16.67% { transform: translateX(120%); z-index: 1; } /* we update the z-order here */
33.34% { transform: translateX(0%); z-index: 1; }
83.33% { transform: translateX(0%); z-index: 1; }
83.34% { transform: translateX(0%); z-index: 2; } /* and also here */
100% { transform: translateX(0%); z-index: 2; }
}
ما آن را بازنشانی کردیم z-index
مقدار 5/6 از طریق انیمیشن (به جای دو سوم) که زمانی است که اولین تصویر از مجموعه خارج شده است. پس ما پرش نمی بینیم!
تادا! نوار لغزنده بی نهایت ما اکنون کامل است! در اینجا کد نهایی ما با تمام شکوه آن است:
.gallery > img {
animation: slide 6s infinite;
}
.gallery > img:last-child {
animation-name: slide-last;
}
.gallery > img:nth-child(2) { animation-delay: -2s; }
.gallery > img:nth-child(3) { animation-delay: -4s; }
@keyframes slide {
0% { transform: translateX(0%); z-index: 2; }
16.66% { transform: translateX(120%); z-index: 2; }
16.67% { transform: translateX(120%); z-index: 1; }
33.34% { transform: translateX(0%); z-index: 1; }
66.33% { transform: translateX(0%); z-index: 1; }
66.34% { transform: translateX(0%); z-index: 2; }
100% { transform: translateX(0%); z-index: 2; }
}
@keyframes slide-last {
0% { transform: translateX(0%); z-index: 2; }
16.66% { transform: translateX(120%); z-index: 2; }
16.67% { transform: translateX(120%); z-index: 1; }
33.34% { transform: translateX(0%); z-index: 1; }
83.33% { transform: translateX(0%); z-index: 1; }
83.34% { transform: translateX(0%); z-index: 2; }
100% { transform: translateX(0%); z-index: 2; }
}
پشتیبانی از هر تعداد تصویر
اکنون که انیمیشن ما برای سه تصویر کار می کند، بیایید آن را برای هر عددی کار کنیم (N
) از تصاویر. اما ابتدا، میتوانیم با تقسیم کردن انیمیشن بهمنظور جلوگیری از افزونگی، کار خود را کمی بهینه کنیم:
.gallery > img {
z-index: 2;
animation:
slide 6s infinite,
z-order 6s infinite steps(1);
}
.gallery > img:last-child {
animation-name: slide, z-order-last;
}
.gallery > img:nth-child(2) { animation-delay: -2s; }
.gallery > img:nth-child(3) { animation-delay: -4s; }
@keyframes slide {
16.67% { transform: translateX(120%); }
33.33% { transform: translateX(0%); }
}
@keyframes z-order {
16.67%,
33.33% { z-index: 1; }
66.33% { z-index: 2; }
}
@keyframes z-order-last {
16.67%,
33.33% { z-index: 1; }
83.33% { z-index: 2; }
}
اکنون کد بسیار کمتری دارد! یک انیمیشن برای قسمت کشویی و یکی دیگر برای قسمت می سازیم z-index
به روز رسانی ها توجه داشته باشید که استفاده می کنیم steps(1)
در z-index
انیمیشن این به این دلیل است که من می خواهم ناگهان تغییر دهم z-index
مقدار، بر خلاف انیمیشن کشویی که در آن ما حرکت صاف را می خواهیم.
اکنون که خواندن و نگهداری کد آسانتر است، دید بهتری برای درک نحوه پشتیبانی از هر تعداد تصویر داریم. کاری که باید انجام دهیم این است که تاخیرهای انیمیشن و درصد فریم های کلیدی را به روز کنیم. تأخیر آسان است زیرا میتوانیم دقیقاً از همان حلقهای که در مقاله گذشته ایجاد کردیم برای پشتیبانی از چندین تصویر در نوار لغزنده دایرهای استفاده کنیم:
@for $i from 2 to ($n + 1) {
.gallery > img:nth-child(#{$i}) {
animation-delay: calc(#{(1 - $i)/$n}*6s);
}
}
این بدان معناست که ما در حال حرکت از وانیلی CSS به Sass هستیم. در مرحله بعد، باید تصور کنیم که مقیاس جدول زمانی چگونه است N
تصاویر. فراموش نکنیم که انیمیشن در سه مرحله اتفاق می افتد:
پس از "slide to right" و "slide to left"، تصویر باید در جای خود بماند تا بقیه تصاویر از طریق دنباله عبور کنند. بنابراین بخش «حرکت نکن» باید به همان اندازه زمان ببرد که (N - 1
) به صورت “slide to right” و “slide to left”. و در یک تکرار، N
تصاویر اسلاید خواهند شد بنابراین، "slide to right" و "slide to left" هر دو گرفته می شوند 100%/N
از کل جدول زمانی انیمیشن تصویر از شمع دور میشود (100%/N)/2
و به عقب می لغزد 100%/N
.
ما می توانیم این را تغییر دهیم:
@keyframes slide {
16.67% { transform: translateX(120%); }
33.33% { transform: translateX(0%); }
}
…به این:
@keyframes slide {
#{50/$n}% { transform: translateX(120%); }
#{100/$n}% { transform: translateX(0%); }
}
اگر جایگزین کنیم N
با 3
، ما گرفتیم 16.67%
و 33.33%
زمانی که وجود دارد 3
تصاویر در پشته این همان منطق با ترتیب انباشته است که در آن ما این را خواهیم داشت:
@keyframes z-order {
#{50/$n}%,
#{100/$n}% { z-index: 1; }
66.33% { z-index: 2; }
}
ما هنوز باید به روز رسانی کنیم 66.33%
نقطه. این قرار است جایی باشد که تصویر آن را بازنشانی می کند z-index
قبل از پایان انیمیشن در همان زمان، تصویر بعدی شروع به اسلاید می کند. از آنجایی که قسمت کشویی طول می کشد 100%/N
، تنظیم مجدد باید در انجام شود 100% - 100%/N
:
@keyframes z-order {
#{50/$n}%,
#{100/$n}% { z-index: 1; }
#{100 - 100/$n}% { z-index: 2; }
}
اما برای ما z-order-last
انیمیشن برای کار، باید کمی بعد در دنباله اتفاق بیفتد. تعمیری را که برای آخرین تصویر انجام دادیم به خاطر دارید؟ ریست کردن z-index
ارزش باید زمانی اتفاق بیفتد که اولین تصویر خارج از شمع باشد و نه زمانی که شروع به لغزش کند. ما میتوانیم از همین استدلال در اینجا در فریمهای کلیدی خود استفاده کنیم:
@keyframes z-order-last {
#{50/$n}%,
#{100/$n}% { z-index: 1; }
#{100 - 50/$n}% { z-index: 2; }
}
ما تمام شدیم! در اینجا چیزی است که هنگام استفاده از پنج تصویر بدست می آوریم:
میتوانیم کمی چرخش اضافه کنیم تا چیزها کمی شیکتر شوند:
تمام کاری که انجام دادم ضمیمه کردن است rotate(var(--r))
به transform
ویژگی. در داخل حلقه، --r
با یک زاویه تصادفی تعریف می شود:
@for $i from 1 to ($n + 1) {
.gallery > img:nth-child(#{$i}) {
--r: #{(-20 + random(40))*1deg}; /* a random angle between -20deg and 20deg */
}
}
چرخش اشکالات کوچکی ایجاد میکند، زیرا گاهی اوقات میتوانیم برخی از تصاویر را ببینیم که به پشت پشته میپرند، اما مشکل بزرگی نیست.
پسگفتار
همه آنها z-index
کار تعادل بزرگی بود، درست است؟ اگر قبل از این تمرین مطمئن نبودید که ترتیب انباشتگی چگونه کار می کند، احتمالاً اکنون ایده بسیار بهتری دارید! اگر دنبال کردن برخی از توضیحات برایتان سخت بود، اکیداً به شما توصیه می کنم دوباره مقاله را بخوانید و با مداد و کاغذ چیزها را ترسیم کنید. سعی کنید هر مرحله از انیمیشن را با استفاده از تعداد متفاوتی از تصاویر به تصویر بکشید تا ترفند را بهتر درک کنید.
دفعه قبل، از چند ترفند هندسی برای ایجاد یک نوار لغزنده دایرهای استفاده کردیم که پس از یک دنباله کامل به تصویر اول برمیگردد. این بار ترفند مشابهی را با استفاده از آن انجام دادیم z-index
. در هر دو مورد، ما هیچ یک از تصاویر را برای شبیه سازی یک انیمیشن پیوسته کپی نکردیم، و همچنین برای کمک به محاسبات به جاوا اسکریپت نرسیدیم.
دفعه بعد اسلایدرهای سه بعدی می سازیم. گوش به زنگ باشید!