برنامه نویسی

Div Div در واقع 3D Cube📦 در CSS خالص! (آنها گفتند غیرممکن است!)

این درست به نظر می رسد درست است؟

منظور من این است که تعداد زیادی مکعب CSS سه بعدی با استفاده از 2 بخش وجود دارد ، و بارهای مکعب با استفاده از یک DIV که استاتیک هستند ، بنابراین انجام یک مکعب چرخان واقعاً سه بعدی در یک DIV چقدر سخت تر است؟

اسپویلرها … خیلی سخت تر!

در واقع من از چند نفر پرسیدم که آیا فکر می کنند این کار قابل انجام است و پاسخی که من دریافت کردم “غیرممکن” بود ، زیرا “CSS فقط به آن نیست”.

اکنون چیزی که شما باید بدانید این است که من دوست دارم “غیرممکن” انجام دهم ، به خصوص با CSS (همانطور که در CSS می خوردم و این باعث می شود من در آن بهتر شود!).

منظور من این است که من فقط یک Highlighter Syntax CSS ساخته ام ، در CSS نوع حباب را مرتب کردم و حتی یک شبکه عصبی را در CSS ساخته ام.

بنابراین مطمئناً من می توانم CSS را فقط یک مکعب 3D 3D درست انجام دهم؟

خوب بگذارید به شما بگویم ، این چالش تقریباً مرا شکست. من سعی کردم این کار را 3 بار انجام دهم و شکست خوردم.

اما امروز ، من بالاخره این کار را کردم.

و من واقعاً معتقدم که این ممکن است بزرگترین کاری باشد که تاکنون انجام داده ام!

می خواهید آن را ببینید؟

البته شما این کار را می کنید ، این تنها دلیلی است که شما در اینجا درست هستید ، برای دیدن اینکه من دروغ می گویم؟

خوب ببین (اعلیحضرت؟ هرج و مرج؟) که یک مکعب سه بعدی در CSS خالص است! (هشدار داده شود ، CSS ممکن است مغز شما را کمی بشکند!)

ادامه دهید ، برگه های HTML ، JS و CSS را بررسی کنید!

همچنین یک نسخه ی نمایشی تعاملی وجود دارد که در پایان این مقاله می توانید چرخش x و y را با کشویی تنظیم کنید


اوه و قبل از اینکه شما در مورد JS چیزی بگویید – که صرفاً موقعیت چرخش را به روشی که مرورگر متقابل باشد ، تنظیم می کند ، اگر می توانستیم از CSS Houdini استفاده کنیم ، اگر برای برخی از مرورگرهای آزار دهنده نبود ، می توانستیم این کار را بدون CSS انجام دهیم.

تمام کاری که انجام می دهد تغییر چرخش مکعب با استفاده از CSS Props به هر حال!

چرا اینقدر سخت بود؟

پاسخ کوتاه با یک بخش واحد است به این معنی است که من فقط 3 طرف برای بازی با آنها داشتم (خود Div ، و ::before وت ::after عناصر شبه

و اگر نمی دانستید ، یک مکعب 6 طرف دارد!

این بدان معنی بود که ما مجبور بودیم آنچه را که به نظر می رسد یک ترفند ساده انجام دهیم ، کار کنیم که 3 طرف با دوربین روبرو هستند و آنها را نشان می دهند.

با این حال ، هرکسی که به صورت سه بعدی کار کرده است ، به شما خواهد گفت ، کار کردن در کدام طرف با دوربین ساده نیست.

منظورم این است که از نظر کد خیلی دشوار نیست ، اما در CSS؟ اینجاست که همه چیز کثیف می شود!

بگذارید شما را با چند چالش که با من روبرو شدم قدم بردارم!

1. محاسبه کدام طرف برای نشان دادن

این به مهارت های جدی ریاضی احتیاج داشت.

خوشبختانه بسیاری دیگر قبل از من این کار را انجام داده اند و من فقط JS را گرفتم و آن را به CSS تبدیل کردم.

اکنون یک نکته عادلانه در این مورد وجود دارد ، اما یکی از مهمترین موارد این است که یک بار یک بار از سحر و جادو سینوسی انجام دهید ، موقعیت x ، y و z از یک شکل را در فضای سه بعدی دارید.

گرفتن مختصات X ، Y و Z از صورت چرخشی مکعب

این همان کاری است که این بیت انجام می دهد:

  /* the "normals" for this side, we repeat these for each side but change  the value to reflect it's position in 3D space (so the back is at z = -1, the left is at x = -1 etc.) */
  --normals-front-x: 0;
  --normals-front-y: 0;
  --normals-front-z: 1;

  /* the calculations to adjust the 3D rotation back to X, Y, Z coordinates */
 --front-y1: calc((var(--normals-front-y) * cos(var(--xRot))) - (var(--normals-front-z) * sin(var(--xRot))));    
  --front-z1: calc(var(--normals-front-y) * sin(var(--xRot)) + var(--normals-front-z) * cos(var(--xRot))); 
  --front-x2: calc(var(--normals-front-x) * cos(var(--yRot)) + var(--front-z1) * sin(var(--yRot)));    
  --front-z2: calc(var(--normals-front-x) * -1 * sin(var(--yRot)) + var(--front-z1) * cos(var(--yRot)));      
  --front-x3: calc(var(--front-x2) * cos(var(--zRot)) - var(--front-y1) * sin(var(--zRot)));      
  --front-y3: calc(var(--front-x2) * sin(var(--zRot)) + var(--front-y1) * cos(var(--zRot)));  
  --front-x: var(--front-x3); 
  --front-y: var(--front-y3);
  --front-z: var(--front-z2);  

 /* repeated for each side of the cube */
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

دریافت موقعیت محور z یا “محصول نقطه”

سپس هنگامی که این موقعیت های X ، Y و Z را داریم (نسبت به ما در فضای سه بعدی) می توانیم “محصول نقطه” آنها را بدست آوریم تا شکل Z را نسبت به جهت دوربین شکل دهند.

این همان کاری است که همه اینها انجام می دهد:

/* getting the magnitude of the camera position. It is worth noting that because I use camera position of X: 0, Y: 0 and Z: 1 this is not really needed as --normalised-cam-z = 1 and --normalised-cam-x and --normalised-cam-y = 0, however I left it in for completeness */

--magnitude-cam: sqrt(calc((var(--normals-camera-x) * var(--normals-camera-x)) + (var(--normals-camera-y) * var(--normals-camera-y)) + (var(--normals-camera-z) * var(--normals-camera-z))));
    --normalised-cam-x: var(--normals-camera-x) / var(--magnitude-cam);
    --normalised-cam-y: var(--normals-camera-y) / var(--magnitude-cam);
    --normalised-cam-z: var(--normals-camera-z) / var(--magnitude-cam);

/* getting the dot-product of the camera normals and the sides X, Y and Z positions and adding them up. */
--dot-prod-front: calc((var(--normals-camera-x) * var(--front-x)) + (var(--normals-camera-y) * var(--front-y)) + (var(--normals-camera-z) * var(--front-z)));
/* repeated for each side */
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

این محصول نقطه فاصله را در امتداد فاصله دوربین یا فاصله در امتداد محور Z (عمق) به ما می دهد.

خوب ، اکنون می توانیم شروع به کار کنیم که طرفین در آن نمایش داده می شوند!

این تنظیمات زیادی است ، اما اکنون ما آنچه را که نیاز داریم داریم ، راهی برای دیدن اینکه کدام 3 چهره نزدیک به دوربین هستند!

این چیزی است که این بیت در مورد همه چیز است:

  --show-front: Min(1, Max(calc(var(--dot-prod-front) * 100 - var(--dot-prod-back) * 100), 0));
--show-back: calc(1 - var(--show-front));
--show-right-dot: Min(1, Max(calc(var(--dot-prod-right) * 100 - var(--dot-prod-left) * 100), 0));
 --show-left-dot: calc(1 - var(--show-right-dot));   
  --show-right: calc(var(--show-right-dot) * var(--X-Not-between-90-270) + var(--show-left-dot) * var(--X-between-90-270));   --show-left: calc(1 - var(--show-right));   
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

ممکن است بلافاصله آشکار نباشد که در اینجا چه اتفاقی می افتد ، بنابراین بیایید آن را تجزیه کنیم.

ما موقعیت z از جبهه و موقعیت z از پشت را می گیریم و آنها را مقایسه می کنیم.

اگر جبهه به ما نزدیکتر از پشت (موقعیت Z بیشتر) باشد ، می خواهیم نشان دهیم که اگر پشت به ما نزدیکتر باشد ، می خواهیم آن را نشان دهیم.

بنابراین همه مزخرفات حداقل مکس چیست؟

خوب ما می خواهیم اعشار را به یک بولی تبدیل کنیم.

بنابراین آنچه ما انجام می دهیم این است:

  • هر دو عدد را 100 برابر کنید (برای اطمینان از اینکه اختلاف آنها احتمالاً بیشتر از 1 است).
  • “جلو” را از “پشت” تفریق کنید ، بنابراین یا یک عدد مثبت یا یک عدد منفی دریافت می کنیم.
  • حداکثر دو عدد و 0 را بدست آورید (بنابراین اگر جلو – برگشت> 0 عدد مثبت را بدست آوریم زیرا از 0 بزرگتر است ، اما اگر جلو – برگشت <0 ما 0 را بدست آوریم زیرا اکنون بزرگتر از عدد منفی است )
  • سپس ما حداقل خروجی قبلی و 1 را دریافت می کنیم ، این برای به دست آوردن هر تعداد مثبت در 1 است.

ما می توانیم همین کار را با clamp(0, front-back, 1) اما به دلایلی من همیشه به این روش می نویسم!

سرانجام یک بولی داریم!

Phew ، این بسیار زیاد بود ، اما اکنون ما یک مقدار بولی داریم که اگر جلو به دوربین نزدیکتر از پشت باشد و ما می توانیم از آن در جلوی/عقب CSS خود استفاده کنیم تا موقعیت سمت را حرکت دهد:

.cube {
 /* other props */
translateZ(calc(
      (var(--show-front) - var(--show-back)) * var(--cube-size) * 0.5
    ));
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

بنابراین یا می گیریم (1 - 0) * 100px * 0.5 (50px) اگر جلو باید نشان دهد و (0 - 1) * 100px * 0.5 (-50px) اگر پشت باید نشان دهد.

سپس ما این را در محور z اعمال می کنیم و گویا با جادو می توانیم بسته به دوربین ، جلوی و پشت شکل را جابجا کنیم (همانطور که شکل می دهیم شکل DOT در چنین راهی تغییر می کند> جلو و جلو و بنابراین ما موقعیت ها را تغییر می دهیم تا با ما روبرو شود)!

ما می توانیم ترفندهای مشابهی را برای چپ / راست و بالا / پایین انجام دهیم ، اما این حتی ساده تر است زیرا می توانیم طرف را با تمام طول مکعب حرکت دهیم:

/* left / right adjustment to move it one cube length to switch sides*/
translateZ(calc(var(--show-right) * var(--cube-size)));

/* top / bottom adjustment */
translateZ(calc(var(--show-top) * var(--cube-size)));
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

و این باید درست باشد؟

خوب نه ، ما یک زن و شوهر از “Gotchyas” داریم ، و به همین دلیل این کار بسیار دشوار شد!

2. موقعیت تغییر جلو و عقب

این یکی مرا گرفت!

از آنجا که ما از یک DIV استفاده می کنیم ، یک مشکل منحصر به فرد داریم.

می بینید ، وقتی موقعیت صورت جلو / عقب را حرکت می دهیم ، موقعیت موقعیت چپ / راست و موقعیت بالا / پایین را با همان میزان حرکت می دهد.

این همه چیز را کاملاً می شکند ، زیرا ما فقط می خواهیم جلو / بازگشت موقعیت را نسبت به کاربر تغییر دهد.

این به این دلیل است که ::before وت ::after عناصر شبه نسبت به اصلی قرار می گیرند .cube عنصر. در .cube حرکت می کند ، آنها حرکت می کنند.

بنابراین ما باید این را در CSS خود حساب کنیم.

به همین دلیل ما دو تغییر در خود داریم ::before وت ::after عناصر psuedo.

transform:
    translate(-50%, 0%)
    /* this transform accounts for the front / back changing position and moves this face by the same amount in the opposite direction so that it stays in the same location */
    translateZ(calc(
      -1 * (var(--show-front) - var(--show-back)) * var(--cube-size) / 2
    ))
    rotateY(90deg)
    translateZ(calc(
      var(--show-right) * var(--cube-size)
    ));
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

وقتی آن را می بینید ، فکر می کنید “خوب است که مستقیم به جلو است” ، اما من مجبور شدم چندین بار نحوه چرخش و قرار دادن طرفین مکعب را به طور کامل تغییر دهم تا این کار ساده شود و واقعاً مغز من را شکست آن را در فضای سه بعدی تجسم کنید (بد! مثل 10 بار من را گرفت!).

به هر حال این یکی را برطرف می کند ، ما باید اکنون انجام شود؟

3. چرخش در حال تغییر چپ / راست و بالا / پایین

تقریباً ، این آخرین مشکل بود!

هنگامی که یک شکل بیش از 90 درجه روی محور x (و کمتر از 270 درجه) می چرخد.

این به دلیل تعویض موقعیت های جلو و عقب و چرخش در فضای سه بعدی است به این معنی که چپ و راست می شود سمت چپ می شود.

ما در حال چرخش در محور Y در 90 و 270 درجه هستیم ، موقعیت های بالا و پایین ما تغییر می کند (نسبت به صورت جلو / عقب).

این همان چیزی است که این کمی از هرج و مرج در مورد:

  --X-above-90: Min(1, Max(calc(var(--rotX) - 90), 0));
    --X-below-90: calc(1 - var(--X-above-90));
    --X-above-270: Min(1, Max(calc(var(--rotX) - 270), 0));
    --X-below-270: calc(1 - var(--X-above-270));
    --X-between-90-270: Max(0, 1 - Max(var(--X-below-90), var(--X-above-270)));
    --X-Not-between-90-270: calc(1 - var(--X-between-90-270));
 /* repeated for the Y axis rotation */
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

به ما اجازه می دهد محاسبه کنیم که آیا چرخش X بین 90 تا 270 است ، بنابراین می توانیم موقعیت های چپ / راست خود را معکوس کنیم ، و برای چرخش Y یکسان است تا بتوانیم موقعیت های بالا / پایین را معکوس کنیم.

به همین دلیل ما داریم --show-right-dot وت --show-right، ما باید آن تحولات را اعمال کنیم:

 --show-right-dot: Min(1, Max(calc(var(--dot-prod-right) * 100 - var(--dot-prod-left) * 100), 0)
    );
    --show-left-dot: calc(1 - var(--show-right-dot));
    --show-right: calc(var(--show-right-dot) * var(--X-Not-between-90-270) + var(--show-left-dot) * var(--X-between-90-270));
    --show-left: calc(1 - var(--show-right));

حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

بیت کلید است --show-right همانطور که اگر یک شاخه بدون شاخه انجام می دهیم!

--show-right: calc(var(--show-right-dot) * var(--X-Not-between-90-270) + var(--show-left-dot) * var(--X-between-90-270)); معادل:

  • right(1) * not between(1) + left(0) * between(0) اگر x <90 یا X> 270 باشد و محصول نقطه ما می گوید درست باید نشان داده شود (خروجی 1 است).
  • right(1) * not between(0) + left(0) * between(1) اگر x بین 90 تا 270 و راست باشد باید نشان دهد (خروجی 0 است – ما راست به سمت چپ تعویض کرده ایم).
  • right(0) * not between(1) + left(1) * between(0) اگر x <90 یا X> 270 باشد و محصول نقطه ما می گوید سمت چپ باید نشان داده شود (خروجی 0 است که باقی مانده است).
  • right(0) * not between(0) + left(1) * between(1) اگر x بین 90 تا 270 و راست باشد باید نشان دهد (خروجی 1 است – ما اکنون ساخته ایم --show-right درست است حتی اگر محصول نقطه ما می گوید سمت چپ باید نشان دهد).

همین است!

خوب ، تقریباً ، ممکن است هنوز هم از این توضیحات پیروی کند.

به نظر من ساده ترین راه برای درک بازی است!

بنابراین در اینجا یک نسخه ی نمایشی وجود دارد که می توانید چرخش X و Y را با استفاده از کشویی تنظیم کرده و سپس موارد را بازرسی کنید.

در پایین چیز جالبی نیز وجود دارد!

این مستطیل های قرمز و سبز حاشیه های خود را توسط خواص CSS که ما در برنامه استفاده می کنیم تنظیم کرده اند ، بنابراین می توانید هنگام حرکت لغزنده ها ، مقادیر را تغییر دهید. اگر اشکال را بازرسی کرده و حاشیه را بررسی کنید ، می توانید مقدار هر خاصیت را مشاهده کنید.

جلو را نشان دهید ، به پشت و غیره نشان دهید. اگر روشن هستند ، 300px را به سمت راست حرکت دهید (و در صورت خاموش بودن در سمت چپ بمانید).

با کشویی ها یک نمایشنامه داشته باشید و ببینید که آیا همه چیز معنا پیدا می کند! 💗

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا