Tantangan Front-End Diterima: CSS 3D Cube

Diterbitkan: 2022-03-10
Ringkasan cepat Apakah Anda suka tantangan? Apakah Anda bersedia mengambil tugas yang belum pernah Anda temui sebelumnya, dan melakukannya di bawah tenggat waktu? Bagaimana jika, dalam menjalankan tugas, Anda menemukan masalah yang tampaknya tidak dapat diselesaikan? Saya ingin berbagi pengalaman saya menggunakan efek 3D CSS untuk pertama kalinya dalam proyek nyata dan menginspirasi Anda untuk menghadapi tantangan. Itu adalah hari yang biasa ketika Eugene, seorang manajer di CreativePeople , menulis kepada saya. Dia mengirimi saya video dan menjelaskan bahwa dia sedang mengembangkan konsep untuk proyek baru dan bertanya-tanya apakah mungkin bagi saya untuk mengembangkan sesuatu seperti yang ada di video.

Apakah Anda suka tantangan? Apakah Anda bersedia mengambil tugas yang belum pernah Anda temui sebelumnya, dan melakukannya di bawah tenggat waktu? Bagaimana jika, dalam menjalankan tugas, Anda menemukan masalah yang tampaknya tidak dapat diselesaikan? Saya ingin berbagi pengalaman saya menggunakan efek 3D CSS untuk pertama kalinya dalam proyek nyata dan menginspirasi Anda untuk menghadapi tantangan.

Itu adalah hari yang biasa ketika Eugene, seorang manajer di CreativePeople, menulis kepada saya. Dia mengirimi saya video dan menjelaskan bahwa dia sedang mengembangkan konsep untuk proyek baru dan bertanya-tanya apakah mungkin bagi saya untuk mengembangkan sesuatu seperti yang ada di video.

Bacaan Lebih Lanjut tentang SmashingMag:

  • Beercamp: Eksperimen Dengan CSS 3D
  • Membuat Bentuk Responsif Dengan Clip-Path Dan Mendobrak Kotak
  • Mari Bermain Dengan CSS yang Dipercepat Perangkat Keras

Itu adalah objek 3D (sebuah balok, tepatnya) yang berputar di sekitar salah satu sumbu. Saya sudah memiliki beberapa pengalaman bekerja dengan CSS 3D, dan sebuah solusi mulai muncul di benak saya. Saya mencari kata kunci di Google seperti "CSS 3D cube" untuk mengonfirmasi ide saya dan menjawab Eugene bahwa itu mungkin.

Lebih banyak setelah melompat! Lanjutkan membaca di bawah ini

Pertanyaan Eugene selanjutnya adalah apakah saya akan menerima proyek tersebut? Saya suka tugas yang rumit, jadi saya tidak bisa menolak. Pada saat itu, saya tidak menyadari apa yang saya hadapi, tetapi saya sangat bertekad.

Pertajam Kapak Anda

Mari kita ingatkan diri kita tentang sumbu — bukan sumbu perang, tetapi garis bilangan, sumbu yang sama seperti dalam sistem koordinat kartesius tiga dimensi yang kita pelajari di sekolah. Seperti yang dikatakan Wikipedia kepada kita:

Sistem koordinat kartesius untuk ruang tiga dimensi adalah triplet berurutan dari garis (sumbu) yang tegak lurus berpasangan, memiliki satu satuan panjang untuk ketiga sumbu dan memiliki orientasi untuk setiap sumbu.

Gambar di bawah ini menunjukkan bagaimana sumbu diorientasikan di browser web.

Sistem koordinat Cartesian tiga dimensi tangan kanan dengan sumbu Z mengarah ke penampil.
Sistem koordinat kartesius tiga dimensi tangan kanan dengan sumbu z mengarah ke penampil. (Gambar: Wikimedia Commons) (Lihat versi besar)

Sumbu x horizontal, sumbu y vertikal, dan sumbu z tampak keluar dari layar ke arah Anda. Nilai nol sumbu z adalah bidang layar. Ingat ini.

Membersihkan Perspektif

Untuk membuat objek 3D, saya membutuhkan elemen (sebut saja "adegan") dengan perspektif. Perspektif adalah kedalaman pemandangan, dan itu tergantung pada ukuran objek yang dikandungnya.

 .scene { perspective: 800px; }

Jika perspektif terlalu kecil, objek bisa terdistorsi. Jika terlalu besar, efek 3D akan berkurang menjadi tidak ada.

Lihat Pena jqgMvL oleh Anna Selezniova (@askd) di CodePen.

Selain itu, hanya ada satu sudut pandang untuk semua objek dalam pemandangan. Dan efek 3D tergantung pada posisi sudut pandang.

Lihat Pena oxKzKv oleh Anna Selezniova (@askd) di CodePen.

Jadi, bagaimana kita menghitung perspektif? Saya menemukan bahwa itu tergantung pada sumbu rotasi. Untuk sumbu x, nilai tinggi dikalikan 4 akan sesuai. Untuk sumbu y, itu akan menjadi nilai lebar dikalikan dengan 4. Inilah rumus ajaib saya:

 const perspective = dimension * 4;

Dilihat Dari Semua Sisi

Setelah menentukan perspektif, saya mulai membuat objek 3D. Saya memilih kubus karena mudah dan dapat diprediksi. Elemen kubus dibuat sebagai div biasa, diposisikan secara relatif, dengan lebar dan tinggi yang ditentukan (misalnya, 200px ). Itu berubah menjadi objek 3D melalui properti transform-style dengan nilai preserve-3d . Ini memberitahu browser untuk membuat semua elemen bersarang sesuai dengan aturan dunia 3D.

Dalam kasus saya, kubus memiliki enam div (atau "sisi"), benar-benar diposisikan. Nama kelas sesuai dengan posisi awal sisi ( back , left , right , top , bottom , front ). Berikut markupnya:

 <div class="scene"> <div class="cube"> <div class="side back"></div> <div class="side left"></div> <div class="side right"></div> <div class="side top"></div> <div class="side bottom"></div> <div class="side front"></div> </div> </div>

Secara default, semua sisi akan berada di satu bidang. Jadi, saya perlu mengatur ulang mereka. Berikut adalah tampilannya:

Lihat Pena mPNwPx oleh Anna Selezniova (@askd) di CodePen.

Dan inilah CSS yang dihasilkan:

 .cube { position:relative; width: 200px; height: 200px; transform-style: preserve-3d; } .side { position: absolute; width: 200px; height: 200px; } .back { transform: translateZ(-100px); } .left { transform: translateX(-100px) rotateY(90deg); } .right { transform: translateX(100px) rotateY(90deg); } .top { transform: translateY(-100px) rotateX(90deg); } .bottom { transform: translateY(100px) rotateX(90deg); } .front { transform: translateZ(100px); }

Untuk memutar kubus, saya mengatur properti transform pada elemen kubus ke sudut rotasi sewenang-wenang di sepanjang sumbu x:

 .cube { transform: rotateX(42deg); }

Mengatasi Kekurangan

Sesuai dengan tugas, saya hanya memutar kubus sepanjang sumbu x, jadi saya tidak perlu sisi kiri atau kanan. Saya menambahkan keterangan untuk menyelaraskan dengan posisi awal sisi yang tersisa.

Saya mulai memutar kubus dan menemukan bahwa keterangan di sisi bawah dan belakang ditampilkan terbalik:

Lihat Pena GZVvMR oleh Anna Selezniova (@askd) di CodePen.

Untuk mengatasi masalah ini, saya memutar masing-masing sisi ini sepanjang sumbu x sebesar 180 derajat:

 .back { transform: translateZ(-100px) rotateX(180deg); } .bottom { transform: translateY(100px) rotateX(270deg); }

Melampaui Layar

Saya mulai mengisi sisi dengan konten nyata dan segera mengalami masalah lain. Saya perlu menampilkan garis putus-putus 1 piksel, tetapi garis itu buram dan tampak buruk.

Lihat Pen VjeBPg oleh Anna Selezniova (@askd) di CodePen.

Saya segera menyadari apa masalahnya. Apakah Anda ingat iklan TV 3D yang gambarnya melampaui layar? Itu adalah sesuatu seperti itu dengan kubus saya.

Jika Anda dapat melihat kubus dari sisi kiri atau kanan, Anda akan melihat bahwa pusatnya berada di bidang layar (nol pada sumbu z) dan sisi depan berada di luar layar. Oleh karena itu, meningkat secara visual dan kabur.

Lihat Pena WwVEMR oleh Anna Selezniova (@askd) di CodePen.

Untuk mengatasi masalah ini, saya menggeser kubus di sepanjang sumbu z untuk menyelaraskan sisi depan ke bidang layar:

 .cube { transform:translateZ(-100px); }

Ini kubusnya sekarang, hampir siap:

Lihat Pen Xdvery oleh Anna Selezniova (@askd) di CodePen.

Menggunakan Angka Ajaib

Saya kira Anda telah memperhatikan bahwa saya menggunakan angka ajaib 100 untuk menggeser sisi sepanjang sumbu. Nilai 100 persis setengah dari tinggi kubus uji saya. Mengapa setengah tinggi? Karena itu akan menjadi jari-jari lingkaran yang tertulis di sisi kubus (yang ternyata persegi).

 const offset = dimension / 2;

Jika saya perlu memutar prisma segitiga, lingkaran itu akan tertulis dalam segitiga. Dalam hal ini, rumus untuk offset adalah sebagai berikut:

 const offset = dimension / (2 * Math.sqrt(3));

Meniup Kubus

Untuk menganggap tugas selesai, saya harus menguji hasilnya di browser yang berbeda.

Gambar yang saya lihat di Internet Explorer membuat saya depresi. Untuk mendapatkan gambaran tentang apa yang saya bicarakan, lihat demo di bawah ini di browser favorit Anda. Saya mengubah satu properti yang mengakibatkan tampilan kubus salah di Internet Explorer. Namun, jangan mengintip kode sumbernya sampai Anda membaca paragraf di bawah demo di bawah ini.

Lihat Pena XKWMwV oleh Anna Selezniova (@askd) di CodePen.

Faktanya adalah bahwa Internet Explorer tidak mendukung properti transform-style dengan nilai preserve-3d . Saya mempelajari hal ini dengan melihat sumber terpercaya saya yang Dapat Saya Gunakan (lihat catatan 1). Dalam demo di atas, saya mengganti preserve-3d dengan flat . Apakah Anda sudah tahu itu? Hei, aku bilang jangan mengintip!

Aku kesal, tapi aku tidak akan menyerah. Masalah adalah kesempatan untuk mempelajari sesuatu yang baru. Selain itu, saya telah menerima tantangan itu.

Mencari Fulcrum

Saya sedang mencari cara untuk membuat objek 3D tanpa menggunakan transform-style: preserve-3d , dan akhirnya saya menemukan properti yang berguna: transform-origin . Ini menentukan titik pusat dari transformasi elemen. Saya telah membuat demo interaktif di bawah ini, yang akan membantu Anda memahami cara kerjanya:

Lihat Pena rLNmBp oleh Anna Selezniova (@askd) di CodePen.

Rotasi 3D elemen dalam demo sangat mirip dengan sisi depan kubus, bukan? Itu yang saya gunakan.

(Omong-omong, apakah Anda mencoba untuk memilih kotak centang backface-visibility: hidden selama rotasi 3D? Properti ini digunakan untuk menyembunyikan bagian belakang elemen selama transformasi 3D.)

Mulai dari Awal Lagi

Saya mulai mengulang kubus. Saya tidak harus berinteraksi dengan pemandangan secara keseluruhan, jadi saya menghapus properti perspective dari elemen scene dan menambahkannya ke setiap transformasi 3D, sehingga sekarang setiap elemen berubah secara independen. Juga, saya menetapkan properti baru untuk setiap sisi: transform-origin dengan nilai yang sama dengan posisi pusat kubus, dan backface-visibility: hidden . Berikut adalah bagaimana gaya telah berubah:

 .scene { } .cube { position: relative; width: 200px; height: 200px; transform: perspective(800px) translateZ(-100px); } .side { position: absolute; transform-origin: 50% 50% -100px; backface-visibility: hidden; }

Saya harus meletakkan sisi-sisinya di tempat yang tepat. Karena properti transform-origin , saya tidak perlu menggesernya, hanya memutarnya di sekitar sumbu. Ini seperti sihir! Mari kita lihat bagaimana tampilannya:

Lihat Pena zBYwEm oleh Anna Selezniova (@askd) di CodePen.

Berikut CSS untuk penempatan sisi-sisinya:

 .back { transform: perspective(800px) rotateY(180deg); } .top { transform: perspective(800px) rotateX(90deg); } .bottom { transform: perspective(800px) rotateX(-90deg); } .front { transform: perspective(800px); }

Dan di sini Anda dapat melihat kubus baru beraksi:

Lihat Pena wWvdXd oleh Anna Selezniova (@askd) di CodePen.

Memberikan Kembali Kepada Caesar Apa Itu Caesar

Kubus kedua terlihat dan berputar sama seperti yang pertama. Tetapi dalam kasus ini, Anda perlu mengubah setiap sisi secara individual. Ini mungkin tidak terlalu mudah, terutama jika Anda ingin mengontrol sudut rotasi menengah.

Selanjutnya, jika Anda membuka demo di Chrome, Anda akan melihat bahwa sisi-sisinya berkedip selama rotasi — sangat membuat frustrasi.

Pada akhirnya, saya menerapkan kedua pendekatan menggunakan tes sederhana dari transform-style: preserve-3d . Kubus pertama adalah yang default. Kubus kedua adalah untuk Internet Explorer dan browser yang tidak mendukung preserve-3d .

Menggunakan Kekuatan Matematika

Akhirnya, saya harus menerapkan efek paralaks. Biasanya efek ini merespon tindakan pengguna, baik itu posisi kursor mouse atau scroll bar. Dalam hal ini, efeknya tergantung pada sudut rotasi.

Lihat Pena QENyqm oleh Anna Selezniova (@askd) di CodePen.

Jadi, data apa yang saya miliki? Pertama, saya memiliki titik awal dan akhir dari posisi teks atau, sederhananya, offset naik dan turun dari tengah sisi. Kedua, saya memiliki angle rotasi kubus.

Saya menghabiskan berjam-jam mencoba mengembangkan formula. Kemudian, saya sadar. Inilah yang terlintas dalam pikiran:

Grafik fungsi sinus dan kosinus
Grafik fungsi sinus dan kosinus (Gambar: Wikimedia Commons) (Lihat versi besar)

Dengan bantuan sinus dan cosinus, saya dengan mudah menghitung offset setiap keterangan menurut sudutnya. Berikut adalah rumus yang saya buat:

 const front_offset = offset * sin(angle) * -1; const bottom_offset = offset * cos(angle); const back_offset = offset * sin(angle); const top_offset = offset * cos(angle) * -1;

Menyimpulkan

Tugas sekarang selesai, dan saya dapat menikmati hasilnya dan membagikannya kepada Anda. Lihat sendiri cara kerjanya. Gunakan tombol gulir atau panah untuk memutar blok promo. Juga, coba tarik segitiga hitam di kanan atas dan bawah untuk mengontrol sudut rotasi secara manual (sayangnya, fitur ini tidak berfungsi di Internet Explorer). Terlihat cukup bagus, bukan? Dan kinerjanya agak tinggi (sekitar 60 frame per detik).

Saya sangat senang telah berpartisipasi dalam pengembangan website ini. Saya telah memperoleh pengalaman yang berguna dalam bekerja dengan CSS 3D dan telah menemukan banyak properti yang menarik. Lebih penting lagi, saya telah belajar bahwa seseorang tidak boleh menyerah; kemungkinan besar Anda akan menemukan cara untuk menyelesaikan tugas.

Saya harap Anda menikmati cerita saya dan sekarang siap untuk menghadapi tantangan baru.