حرکت بخش اصلی هر تجربه دیجیتالی است که کاربر شما را از یک تعامل به تعامل دیگر هدایت می کند. اما چند شکاف در انیمیشن های روان در بستر وب وجود دارد. اینها شامل امکان متحرک سازی آسان انیمیشن های ورودی و خروجی، و متحرک سازی روان به لایه بالا و از لایه بالایی برای عناصر غیرقابل رد مانند دیالوگ ها و پاپاورها است.
برای پر کردن این شکافها، کروم 116 و 117 شامل چهار ویژگی جدید پلتفرم وب هستند که انیمیشنها و انتقالها را برای ویژگیهای گسسته امکانپذیر میکنند.
این چهار ویژگی جدید عبارتند از:
- امکان متحرک سازی
display
وcontent-visibility
در یک جدول زمانی فریم کلیدی (از Chrome 116). - ویژگی
transition-behavior
با کلمه کلیدیallow-discrete
برای فعال کردن انتقال خصوصیات گسسته مانندdisplay
(از Chrome 117). - قانون
@starting-style
برای متحرک سازی جلوه های ورودی ازdisplay: none
و در لایه بالایی (از Chrome 117). - ویژگی
overlay
برای کنترل رفتار لایه بالایی در طول یک انیمیشن (از Chrome 117).
نمایش انیمیشن ها در فریم های کلیدی
از Chrome 116، میتوانید display
و content-visibility
در قوانین فریم کلیدی استفاده کنید. اینها سپس در زمانی که فریم کلیدی رخ می دهد، با هم عوض می شوند. برای پشتیبانی از این به مقادیر جدید اضافی نیاز نیست:
.card {
animation: fade-out 0.5s forwards;
}
@keyframes fade-out {
100% {
opacity: 0;
display: none;
}
}
مثال قبلی کدورت را روی 0 در مدت زمان 0.5 ثانیه متحرک می کند و سپس نمایش را روی هیچ تنظیم می کند. علاوه بر این، کلمه کلیدی forwards
تضمین می کند که انیمیشن در حالت پایانی خود باقی می ماند، به طوری که عنصری که روی آن اعمال می شود display: none
و opacity: 0
.
این یک مثال ساده است که کارهایی را که میتوانید با یک انتقال انجام دهید تقلید میکند (دمو در بخش انتقال را ببینید). با این حال، انتقالها قادر به ایجاد انیمیشنهای پیچیدهتر نیستند، مانند مثال زیر:
.card {
animation: spin-and-delete 1s ease-in forwards;
}
@keyframes spin-and-delete {
0% {
transform: rotateY(0);
filter: hue-rotate(0);
}
80% {
transform: rotateY(360deg);
filter: hue-rotate(180deg);
opacity: 1;
}
100% {
opacity: 0;
display: none;
}
}
انیمیشن spin-and-delete
یک انیمیشن خروجی است. ابتدا کارت روی محور y میچرخد، از طریق یک چرخش رنگی اجرا میشود، و سپس با 80%
در خط زمانی، کدورت خود را از 1 به 0 تغییر میدهد. در نهایت، کارت از display: block
به display: none
.
برای این انیمیشن های خروجی، به جای اعمال مستقیم آن ها بر روی یک عنصر، می توانید یک ماشه برای انیمیشن ها تنظیم کنید. برای مثال، با پیوست کردن شنونده رویداد به دکمهای که کلاسی را برای اعمال انیمیشن فعال میکند، مانند:
.spin-out {
animation: spin-and-delete 1s ease-in forwards;
}
document.querySelector('.delete-btn').addEventListener('click', () => {
document.querySelector('.card').classList.add('spin-out');
})
مثال بالا اکنون دارای یک حالت پایانی display:none
. موارد زیادی وجود دارد که میخواهید آن را بیشتر کنید و گره DOM را با یک بازه زمانی حذف کنید تا ابتدا انیمیشن به پایان برسد.
انتقال انیمیشن های گسسته
برخلاف زمانی که ویژگیهای گسسته را با فریمهای کلیدی متحرک میکنید، برای انتقال ویژگیهای گسسته، باید از حالت رفتار انتقال allow-discrete
استفاده کنید.
ویژگی transition-behavior
حالت allow-discrete
چیزی است که انتقال گسسته را ممکن میکند و مقداری از ویژگی transition-behavior
است. transition-behavior
دو مقدار را می پذیرد: normal
و allow-discrete
.
.card {
transition: opacity 0.25s, display 0.25s;
transition-behavior: allow-discrete; /* Note: be sure to write this after the shorthand */
}
.card.fade-out {
opacity: 0;
display: none;
}
کوتاهنویسی transition
نیز این مقدار را تعیین میکند، بنابراین میتوانید این ویژگی را حذف کنید و به جای آن از کلمه کلیدی allow-discrete
در انتهای خلاصهنویسی transition
برای هر انتقال استفاده کنید.
.card {
transition: opacity 0.5s, display 0.5s allow-discrete;
}
.card.fade-out {
opacity: 0;
display: none;
}
اگر چندین ویژگی گسسته را متحرک می کنید، باید پس از هر ویژگی که می خواهید متحرک سازی کنید، allow-discrete
اضافه کنید. به عنوان مثال:
.card {
transition: opacity 0.5s, display 0.5s allow-discrete, overlay 0.5s allow-discrete;
}
.card.fade-out {
opacity: 0;
display: none;
}
قانون @starting-style
برای انیمیشن های ورودی
تاکنون، این مقاله به انیمیشنهای خروجی پرداخته است، برای ایجاد انیمیشنهای ورودی باید از قانون @starting-style
استفاده کنید.
از @starting-style
برای اعمال سبکی استفاده کنید که مرورگر بتواند قبل از باز شدن عنصر در صفحه جستجو کند. این حالت "قبل از باز" است (جایی که از آن در حال انیمیشن هستید).
/* 0. IS-OPEN STATE */
/* The state at which the element is open + transition logic */
.item {
height: 3rem;
display: grid;
overflow: hidden;
transition: opacity 0.5s, transform 0.5s, height 0.5s, display 0.5s allow-discrete;
}
/* 1. BEFORE-OPEN STATE */
/* Starting point for the transition */
@starting-style {
.item {
opacity: 0;
height: 0;
}
}
/* 2. EXITING STATE */
/* While it is deleting, before DOM removal in JS, apply this
transformation for height, opacity, and a transform which
skews the element and moves it to the left before setting
it to display: none */
.is-deleting {
opacity: 0;
height: 0;
display: none;
transform: skewX(50deg) translateX(-25vw);
}
اکنون برای این موارد لیست TODO هم حالت ورود و هم خروج دارید:
متحرک سازی عناصر به و از لایه بالایی
برای متحرک سازی عناصر به لایه بالا و از آن، @starting-style
در حالت "باز" مشخص کنید تا به مرورگر بگویید از کجا متحرک شود. برای یک گفتگو، حالت باز با ویژگی [open]
تعریف می شود. برای پاپاور، از کلاس شبه :popover-open
استفاده کنید.
یک مثال ساده از یک دیالوگ می تواند به شکل زیر باشد:
/* 0. IS-OPEN STATE */
dialog[open] {
translate: 0 0;
}
/* 1. BEFORE-OPEN STATE */
@starting-style {
dialog[open] {
translate: 0 100vh;
}
}
/* 2. EXIT STATE */
dialog {
transition: translate 0.7s ease-out, overlay 0.7s ease-out allow-discrete, display 0.7s ease-out allow-discrete;
translate: 0 100vh;
}
در مثال بعدی، جلوه های ورود و خروج متفاوت است. با متحرک سازی از پایین درگاه نمای به بالا وارد شوید، از افکت به بالای نمای درگاه خارج شوید. همچنین با CSS تودرتو برای کپسوله سازی بصری بیشتر نوشته شده است.
هنگام متحرک سازی یک پاپاور، به جای ویژگی open
که قبلا استفاده شده بود، از کلاس شبه :popover-open
استفاده کنید.
.settings-popover {
&:popover-open {
/* 0. IS-OPEN STATE */
/* state when popover is open, BOTH:
what we're transitioning *in* to
and transitioning *out* from */
transform: translateY(0);
opacity: 1;
/* 1. BEFORE-OPEN STATE */
/* Initial state for what we're animating *in* from,
in this case: goes from lower (y + 20px) to center */
@starting-style {
transform: translateY(20px);
opacity: 0;
}
}
/* 2. EXIT STATE */
/* Initial state for what we're animating *out* to ,
in this case: goes from center to (y - 50px) higher */
transform: translateY(-50px);
opacity: 0;
/* Enumerate transitioning properties,
including display and allow-discrete mode */
transition: transform 0.5s, opacity 0.5s, display 0.5s allow-discrete;
}
خاصیت overlay
در نهایت، برای محو کردن یک popover
یا dialog
از لایه بالایی، ویژگی overlay
را به لیست انتقالات خود اضافه کنید. popover
و dialog
از اجداد کلیپ ها و تبدیل ها فرار می کنند و همچنین محتوا را در لایه بالایی قرار می دهند. اگر overlay
انتقال را انجام ندهید، عنصر شما فوراً به حالت بریده شدن، تبدیل شدن و پوشاندن برمیگردد و شما شاهد وقوع این انتقال نخواهید بود.
[open] {
transition: opacity 1s, display 1s allow-discrete;
}
درعوض، overlay
در انتقال یا انیمیشن برای متحرک سازی overlay
همراه با بقیه ویژگی ها قرار دهید و اطمینان حاصل کنید که هنگام انیمیشن در لایه بالایی باقی می ماند. این بسیار نرمتر به نظر می رسد.
[open] {
transition: opacity 1s, display 1s allow-discrete, overlay 1s allow-discrete;
}
علاوه بر این، هنگامی که چندین عنصر در لایه بالایی باز دارید، روکش به شما کمک می کند تا انتقال صاف به داخل و خارج از لایه بالایی را کنترل کنید. می توانید تفاوت را در این مثال ساده ببینید. اگر هنگام انتقال پاپاور دوم به بیرون overlay
استفاده نکنید، قبل از شروع انتقال، ابتدا از لایه بالایی خارج می شود و پشت پاپاور دیگر می پرد. این یک اثر خیلی صاف نیست.
یادداشتی در مورد انتقال مشاهده
اگر در حال ایجاد تغییرات در DOM هستید، مانند افزودن و حذف عناصر از DOM، راه حل عالی دیگر برای انیمیشن های روان، انتقال مشاهده است. در اینجا دو نمونه از نمونه های بالا با استفاده از انتقال view ساخته شده اند.
در این اولین نسخه ی نمایشی، به جای راه اندازی @starting-style
و دیگر تبدیل های CSS، انتقال های view این انتقال را انجام می دهند. انتقال view به این صورت تنظیم می شود:
ابتدا، در CSS، به هر کارت یک view-transition-name
اختصاص دهید.
.card-1 {
view-transition-name: card-1;
}
.card-2 {
view-transition-name: card-2;
}
/* etc. */
سپس، در جاوا اسکریپت، جهش DOM (در این مورد، حذف کارت) را در یک انتقال view قرار دهید.
deleteBtn.addEventListener('click', () => {
// Check for browser support
if (document.startViewTransition) {
document.startViewTransition(() => {
// DOM mutation
card.remove();
});
}
// Alternative if no browser support
else {
card.remove();
}
})
اکنون، مرورگر می تواند محو شدن و تغییر شکل هر کارت را در موقعیت جدید خود کنترل کند.
نمونه دیگری از مواردی که میتواند مفید باشد، استفاده از نسخه نمایشی افزودن/حذف آیتمهای فهرست است. در این مورد، باید به خاطر داشته باشید که برای هر کارت ایجاد شده یک view-transition-name
منحصر به فرد اضافه کنید.
نتیجه گیری
این ویژگیهای پلتفرم جدید ما را یک قدم به انیمیشنهای ورود و خروج روان در پلتفرم وب نزدیکتر میکنند. برای کسب اطلاعات بیشتر، این لینک ها را بررسی کنید: