ترنسفورم دوبعدی و سه‌بعدی؛ وقتی عمق وارد بازی می‌شه

تا اینجا با translate، scale، rotate و skew آشنا شدیم و همه‌شون رو به‌صورت جداگانه امتحان کردیم. اما یه نکته‌ی خیلی مهم هست که تا الان بهش اشاره نکرده بودیم: همه‌ی این تبدیل‌ها رو می‌شه هم به‌صورت دوبعدی (2D) و هم سه‌بعدی (3D) انجام داد. تو این درس می‌خوایم دقیق‌تر ببینیم فرق این دو تا چیه و چطور می‌تونیم یه المنت رو واقعاً تو فضا بچرخونیم، نه فقط رو صفحه.

فرق ترنسفورم 2D و 3D چیه؟

وقتی از توابعی مثل translateX() یا rotate() استفاده می‌کنیم، داریم رو یه صفحه‌ی مسطح کار می‌کنیم؛ یعنی فقط محور X و Y وجود داره. ولی مرورگر یه محور سوم هم داره به اسم Z، که عمود بر صفحه‌ی مانیتوره؛ رو به سمت چشم شما یا دور از چشم شما. وقتی از توابع سه‌بعدی استفاده می‌کنیم، داریم از این محور Z هم استفاده می‌کنیم.

تابع 2Dمعادل یا نسخه‌ی 3Dتوضیح
translate(x, y)translate3d(x, y, z)جابه‌جایی، حالا با عمق
rotate(angle)rotateX(), rotateY(), rotateZ()چرخش حول هر یک از سه محور
scale(x, y)scale3d(x, y, z)بزرگ‌نمایی در سه بعد

چرخش حول محورهای X و Y

تابع rotate() که قبلاً دیدیم، در واقع مخفف rotateZ() هست؛ یعنی چرخش حول محوری که از وسط صفحه به سمت شما میاد. اما وقتی از rotateX() یا rotateY() استفاده می‌کنید، المنت انگار داره حول یه لولای افقی یا عمودی می‌چرخه:

.card {
  transition: transform 0.6s ease;
}

.card:hover {
  transform: rotateY(180deg);
}

اگه همین الان این کد رو تست کنید، احتمالاً یه چیز عجیب می‌بینید: المنت واقعاً «برعکس» نمی‌شه و بیشتر شبیه اینه که از عرض جمع بشه و دوباره باز بشه، بدون این‌که هیچ حس عمقی داشته باشه. این دقیقاً همون مشکلی هست که تو بخش بعد حلش می‌کنیم.

چرا بدون perspective، سه‌بعدی بودن دیده نمی‌شه؟

مرورگر به‌طور پیش‌فرض صفحه رو مثل یه دوربین با فاصله‌ی بی‌نهایت از سوژه می‌بینه؛ یعنی هیچ منظری (perspective) وجود نداره و در نتیجه چرخش حول X یا Y فقط باعث فشرده شدن المنت می‌شه، نه چرخیدنش تو فضا. برای این‌که واقعاً حس سه‌بعدی بودن رو حس کنید، باید به المنت والد یه ویژگی به اسم perspective بدید:

.container {
  perspective: 800px;
}

.card {
  transition: transform 0.6s ease;
}

.card:hover {
  transform: rotateY(180deg);
}

عدد perspective رو می‌شه مثل فاصله‌ی چشم شما از صفحه در نظر گرفت. هرچی این عدد کوچیک‌تر باشه (مثلاً 200px)، افکت سه‌بعدی شدیدتر و اغراق‌آمیزتر می‌شه؛ انگار خیلی نزدیک به صفحه واستادید. هرچی عدد بزرگ‌تر باشه (مثلاً 1500px)، افکت ملایم‌تر و طبیعی‌تره.

یه نکته: می‌تونید perspective رو مستقیم روی خود المنتی که می‌چرخه هم بذارید (به‌جای والدش)، ولی اون‌وقت رفتارش با perspective روی والد فرق می‌کنه؛ معمولاً گذاشتنش روی والد، برای کارت‌ها و افکت‌های flip، نتیجه‌ی طبیعی‌تری می‌ده.

ترکیب چند تبدیل سه‌بعدی با هم

دقیقاً مثل حالت دوبعدی، می‌تونید چند تابع سه‌بعدی رو پشت سر هم تو یه transform بنویسید:

.box {
  transform: translateZ(50px) rotateX(20deg) rotateY(30deg);
}

ترتیب نوشتن اینجا هم مثل قبل مهمه؛ چون هر تبدیل رو المنتی که از تبدیل قبلی خروجی گرفته اعمال می‌کنه، نه المنت اصلی.

transform-style: چیزی که خیلی‌ها فراموشش می‌کنن

اگه یه المنت سه‌بعدی، خودش هم بچه‌های سه‌بعدی داشته باشه (مثلاً یه مکعب که از چند تا وجه تشکیل شده)، باید به والد بگید که فرزندهاش رو هم تو همون فضای سه‌بعدی نگه داره، وگرنه مرورگر همه‌چیز رو صاف می‌کنه:

.scene {
  perspective: 1000px;
}

.cube {
  transform-style: preserve-3d;
  transform: rotateX(-20deg) rotateY(30deg);
}

مقدار پیش‌فرض این ویژگی flat هست، یعنی همه‌چیز رو تخت می‌کنه. اگه می‌خواید یه ساختار واقعاً سه‌بعدی مثل مکعب یا کارت چرخان بسازید، حتماً باید preserve-3d رو تنظیم کنید.

نکته مهم: ویژگی backface-visibility: hidden هم اغلب همراه با ترنسفورم‌های 3D استفاده می‌شه. وقتی یه المنت 180 درجه می‌چرخه، بدون این ویژگی، پشت المنت (که آینه‌ی وارونه‌ی جلوشه) هم دیده می‌شه. با تنظیم این مقدار رو hidden، وقتی پشت یه المنت رو به کاربر باشه، به‌جای نمایش نسخه‌ی آینه‌ای، مخفی می‌شه.

یه مثال کامل: کارت چرخان

.flip-container {
  perspective: 1000px;
}

.flip-card {
  position: relative;
  width: 200px;
  height: 280px;
  transform-style: preserve-3d;
  transition: transform 0.7s;
}

.flip-container:hover .flip-card {
  transform: rotateY(180deg);
}

.flip-front,
.flip-back {
  position: absolute;
  width: 100%;
  height: 100%;
  backface-visibility: hidden;
}

.flip-back {
  transform: rotateY(180deg);
}

این الگو رو زیاد تو سایت‌های فروشگاهی می‌بینید؛ کارت محصول که با هاور برعکس می‌شه و اطلاعات بیشتری نشون می‌ده. نکته‌ی جالب اینه که پشت کارت از اول همون‌جا هست، فقط با rotateY(180deg) و backface-visibility مخفی نگه داشته می‌شه تا لحظه‌ی چرخش.

جمع‌بندی

ترنسفورم سه‌بعدی در واقع همون ابزارهای قبلی هستن، فقط با اضافه شدن محور Z. کلید اصلی برای دیدن افکت واقعی سه‌بعدی، ویژگی perspective روی والده، و اگه فرزندهای المنت هم قراره تو فضای سه‌بعدی بمونن، نباید transform-style: preserve-3d رو فراموش کنید. این سه‌تا (perspective، transform-style، backface-visibility) معمولاً با هم میان و پایه‌ی خیلی از افکت‌های جذاب مثل کارت‌های چرخان و مکعب‌های سه‌بعدی هستن.