Cara Mendekati Animasi SVG di CSS

Diterbitkan: 2022-03-11

Animasi adalah bagian web yang ada di mana-mana. Berbeda dengan gambar GIF berkedip yang menjangkiti situs web di hari-hari sebelumnya di internet, animasi hari ini lebih halus dan berselera tinggi. Desainer dan spesialis front-end menggunakannya untuk membuat situs web terlihat lebih halus, meningkatkan pengalaman pengguna, menarik perhatian ke elemen penting, dan menyampaikan informasi.

Pengembang web bisa mendapatkan keuntungan dari menggabungkan kekuatan SVG dan CSS untuk membuat animasi tanpa menggunakan perpustakaan eksternal. Tutorial animasi SVG ini menunjukkan cara membuat animasi kustom untuk proyek dunia nyata.

Animasi SVG Menggunakan CSS: Konsep Inti

Sebelum menganimasikan SVG dengan CSS, developer perlu memahami cara kerja SVG secara internal. Untungnya, ini mirip dengan HTML: Kami mendefinisikan elemen SVG dengan sintaks XML dan menatanya dengan CSS, seolah-olah mereka adalah HTML.

Elemen SVG sengaja dibuat untuk menggambar grafik. Kita dapat menggunakan <rect> untuk menggambar persegi panjang, <circle> untuk menggambar lingkaran, dll.—SVG juga mendefinisikan <ellipse> , <line> , <polyline> , <polygon> , dan <path> .

Catatan: Daftar lengkap elemen SVG bahkan menyertakan <animate> , yang memungkinkan Anda membuat animasi menggunakan bahasa integrasi multimedia tersinkronisasi (SMIL). Namun, masa depannya tidak pasti dan tim Chromium merekomendasikan penggunaan pendekatan berbasis CSS atau JavaScript untuk menganimasikan SVG bila memungkinkan.

Atribut yang tersedia bergantung pada elemen, jadi sementara <rect> memiliki atribut width dan height , elemen <circle> memiliki atribut r , yang mendefinisikan radiusnya.

Tiga elemen dasar SVG (persegi panjang, lingkaran, dan garis) dan atribut yang tersedia. Persegi panjang ditentukan oleh koordinat x dan y dari sudut kiri atas, serta lebar dan tingginya, misalnya <rect x="25" y="25" width="150" height="100 "/>. Lingkaran ditentukan oleh koordinat x dan y dari pusatnya (cx, cy) diikuti dengan jari-jarinya (r), mis., <circle cx="75" cy="75" r="50"/>. Garis didefinisikan menggunakan koordinat awal (x1 dan y1) dan koordinat akhir (x2 dan y2), mis., <line x1="40" y1="140 x2="140" y2="40"/>.
Pilih elemen SVG dasar; koordinat relatif terhadap asal (sudut kiri atas viewport SVG).

Sementara sebagian besar elemen HTML dapat memiliki anak, sebagian besar elemen SVG tidak bisa. Satu pengecualian adalah elemen grup <g> , yang dapat kita gunakan untuk menerapkan gaya dan transformasi CSS ke beberapa elemen sekaligus.

Elemen <svg> dan Atributnya

Perbedaan penting lainnya antara HTML dan SVG adalah bagaimana kita memposisikan elemen, terutama melalui atribut viewBox dari elemen <svg> luar yang diberikan. Nilainya terdiri dari empat angka yang dipisahkan oleh spasi atau koma: min-x , min-y , width , dan height . Bersama-sama, ini menentukan berapa banyak gambar SVG yang kita inginkan untuk dirender oleh browser. Area tersebut akan diskalakan agar sesuai dengan batas viewport , seperti yang ditentukan oleh atribut width dan height dari elemen <svg> .

Dalam hal letterboxing, rasio atribut width dan height dari viewport mungkin memang berbeda dari rasio bagian width dan height dari atribut viewBox .

Secara default, rasio aspek kanvas SVG akan dipertahankan dengan mengorbankan viewBox yang lebih besar dari yang ditentukan, sehingga menyebabkan rendering letterbox yang lebih kecil di dalam viewport. Tetapi Anda dapat menentukan perilaku yang berbeda melalui atribut preserveAspectRatio .

Hal ini memungkinkan kita untuk menggambar gambar secara terpisah dan yakin bahwa semua elemen akan diposisikan dengan benar terlepas dari konteks atau ukuran rendering.

Gambar yang menunjukkan bagaimana viewBox dirender menjadi viewport dengan rasio aspek berbeda sambil mempertahankan rasio aspek konten. Di sebelah kiri, kotak tampilan persegi panjang memiliki kubus isometrik di tengahnya. Di sebelah kanan, area pandang persegi yang lebih besar memiliki kubus isometrik yang sama, dipusatkan dan diperbesar, sambil mempertahankan rasio aspek kubus.
Mempertahankan rasio aspek gambar melalui letterboxing.

Meskipun Anda dapat membuat kode gambar SVG dengan tangan, gambar yang lebih kompleks mungkin memerlukan program grafik vektor (tutorial animasi SVG kami menunjukkan kedua teknik tersebut). Editor pilihan saya adalah Affinity Designer, tetapi editor mana pun harus menyediakan fungsionalitas yang cukup untuk operasi sederhana yang dibahas di sini.

Transisi dan Animasi CSS

Transisi CSS memungkinkan kita untuk menentukan tingkat dan durasi perubahan properti. Alih-alih melompat secara instan dari nilai awal ke nilai akhir, nilai-nilai bertransisi dengan mulus seperti dalam contoh ini di mana warna lingkaran SVG berubah saat Anda mengarahkan kursor ke atasnya dengan mouse:

Lihat contoh Transisi Pena oleh Filip Defar (@dabrorius) di CodePen.

Kita dapat mendefinisikan transisi dengan properti transition , yang menerima nama properti yang ingin kita transisikan, durasi transisi, fungsi pengaturan waktu transisi (juga dikenal sebagai fungsi easing), dan panjang penundaan sebelum efek dimulai :

 /* property name | duration | easing function | delay */ transition: margin-right 4s ease-in-out 1s;

Kita dapat menentukan transisi untuk beberapa properti CSS, yang masing-masing dapat memiliki nilai transisi yang terpisah. Namun, ada dua batasan yang jelas untuk pendekatan ini.

Batasan pertama adalah bahwa transisi dipicu secara otomatis ketika nilai properti berubah. Ini tidak nyaman dalam beberapa kasus penggunaan. Misalnya, kita tidak dapat memiliki animasi yang berputar tanpa batas.

Batasan kedua adalah bahwa transisi selalu memiliki dua langkah: keadaan awal dan keadaan akhir. Kami dapat memperpanjang durasi animasi, tetapi kami tidak dapat menambahkan bingkai utama yang berbeda.

Inilah sebabnya mengapa ada konsep yang lebih kuat: animasi CSS. Dengan animasi CSS, kita dapat memiliki beberapa keyframe dan infinite loop:

Lihat contoh Animasi Pena oleh Filip Defar (@dabrorius) di CodePen.

Untuk menganimasikan properti CSS pada beberapa keyframe, pertama-tama kita perlu mendefinisikan keyframe menggunakan @keyframes at-rule. Waktu keyframe didefinisikan dalam unit relatif (persentase) karena pada titik ini, kami belum menentukan durasi animasi. Setiap bingkai utama menjelaskan nilai dari satu atau lebih properti CSS pada saat itu. Animasi CSS akan memastikan transisi yang mulus antar keyframe.

Kami menerapkan animasi dengan bingkai utama yang dijelaskan ke elemen yang diinginkan menggunakan properti animation . Mirip dengan properti transition , ia menerima durasi, fungsi easing, dan penundaan.

Satu-satunya perbedaan adalah bahwa parameter pertama adalah nama @keyframes kami, bukan nama properti:

 /* @keyframes name | duration | easing-function | delay */ animation: my-sliding-animation 3s linear 1s;

Menghidupkan Menu Hamburger Toggle

Sekarang setelah kita memiliki pemahaman dasar tentang cara kerja SVG, kita dapat mulai membuat animasi klasik—pengalihan menu yang dengan mulus bertransisi antara ikon "hamburger" dan tombol tutup ("X"):

Lihat Pen Hamburger oleh Filip Defar (@dabrorius) di CodePen.

Ini adalah animasi yang halus namun berharga. Ini menarik perhatian pengguna, memberi tahu mereka bahwa ikon dapat digunakan untuk menutup menu.

Kami memulai demonstrasi kami dengan membuat elemen SVG dengan tiga baris:

 <svg class="hamburger"> <line x1="0" y1="50%" x2="100%" y2="50%" class="hamburger__bar hamburger__bar--top" /> <line x1="0" y1="50%" x2="100%" y2="50%" class="hamburger__bar hamburger__bar--mid" /> <line x1="0" y1="50%" x2="100%" y2="50%" class="hamburger__bar hamburger__bar--bot" /> </svg>

Setiap baris memiliki dua set atribut. x1 dan y1 mewakili koordinat awal garis, sedangkan x2 dan y2 mewakili koordinat akhir garis. Kami telah menggunakan unit relatif untuk mengatur posisi. Ini adalah cara sederhana untuk memastikan bahwa konten gambar diubah ukurannya agar sesuai dengan elemen SVG yang terkandung. Meskipun pendekatan ini berfungsi dalam kasus ini, ada satu kelemahan besar: Kami tidak dapat mempertahankan rasio aspek elemen yang diposisikan dengan cara ini. Untuk itu, kita harus menggunakan atribut viewBox dari elemen <svg> .

Perhatikan bahwa kami menerapkan kelas CSS ke elemen SVG. Ada banyak properti yang dapat diubah melalui CSS, jadi mari kita terapkan beberapa gaya dasar ke elemen SVG kita.

Kami akan mengatur ukuran elemen <svg> , serta mengubah jenis kursor untuk menunjukkan bahwa itu dapat diklik. Tapi untuk mengatur warna dan ketebalan garis, kita akan menggunakan properti stroke dan stroke-width . Anda mungkin mengira akan menggunakan color atau border , tetapi tidak seperti <svg> itu sendiri, sub-elemen SVG bukanlah elemen HTML, sehingga sering kali memiliki nama properti yang berbeda:

 .hamburger { width: 62px; height: 62px; cursor: pointer; } .hamburger__bar { stroke: white; stroke-width: 10%; }

Jika kita merender pada titik ini, kita akan melihat bahwa ketiga garis memiliki ukuran dan posisi yang sama, saling tumpang tindih sepenuhnya. Sayangnya, kami tidak dapat mengubah posisi awal dan akhir secara independen melalui CSS, tetapi kami dapat memindahkan seluruh elemen. Mari pindahkan bilah atas dan bawah dengan properti transform CSS:

 .hamburger__bar--top { transform: translateY(-40%); } .hamburger__bar--bot { transform: translateY(40%); }

Dengan memindahkan palang pada sumbu Y, kita akan mendapatkan hamburger yang terlihat bagus.

Sekarang saatnya mengkode status kedua kita: tombol tutup. Kami mengandalkan kelas CSS .is-opened diterapkan ke elemen SVG untuk beralih di antara dua status. Untuk membuat hasilnya lebih mudah diakses, mari bungkus SVG kita dalam elemen <button> dan tangani klik pada level itu.

Proses penambahan dan penghapusan kelas akan ditangani oleh cuplikan JavaScript sederhana:

 const hamburger = document.querySelector("button"); hamburger.addEventListener("click", () => { hamburger.classList.toggle("is-opened"); });

Untuk membuat X kami, kami dapat menerapkan properti transform yang berbeda ke bar hamburger kami. Karena properti transform yang baru akan menggantikan properti yang lama, titik awal kita akan menjadi posisi bersama yang asli dari tiga batang.

Dari sana, kita dapat memutar bilah atas 45 derajat searah jarum jam di sekitar pusatnya, dan memutar bilah bawah 45 derajat berlawanan arah jarum jam. Kita dapat mengecilkan bilah tengah secara horizontal hingga cukup sempit untuk disembunyikan di belakang pusat X:

 .is-opened .hamburger__bar--top { transform: rotate(45deg); } .is-opened .hamburger__bar--mid { transform: scaleX(0.1); } .is-opened .hamburger__bar--bot { transform: rotate(-45deg); }

Secara default, properti transform-origin untuk elemen SVG biasanya 0,0 . Ini berarti bar kita akan diputar di sekitar sudut kiri atas viewport, tapi kita ingin bar itu berputar di sekitar tengah. Untuk memperbaikinya, mari atur properti transform-origin ke center untuk kelas .hamburger__bar .

Menganimasikan Properti CSS Dengan transition

Properti CSS transition memberi tahu browser untuk bertransisi dengan lancar antara dua status properti CSS yang berbeda. Di sini kita ingin menganimasikan perubahan kita pada properti transform , yang menentukan posisi, orientasi, dan skala batang.

Kami juga dapat mengontrol durasi transisi menggunakan properti transition-duration . Untuk membuat animasi terlihat tajam, kami akan mengatur durasi pendek 0,3 detik:

 .hamburger__bar { transition-property: transform; transition-duration: 0.3s; ... }

Satu-satunya bagian dari JavaScript yang kita butuhkan adalah bit yang membuat status ikon dapat diubah:

 const hamburger = document.querySelector("button"); hamburger.addEventListener("click", () => { hamburger.classList.toggle("is-opened"); });

Di sini, kami memilih elemen SVG luar dengan kelas .mute -nya menggunakan querySelector() . Kami kemudian menambahkan pendengar acara klik. Saat peristiwa klik dipicu, kami mengaktifkan kelas .is-active hanya di <svg> itu sendiri—tidak lebih dalam di hierarki. Karena kita membuat animasi CSS hanya berlaku untuk elemen dengan kelas .is-active , mengubah kelas ini akan mengaktifkan dan menonaktifkan animasi.

Sebagai sentuhan terakhir, kita akan mengonversi badan HTML menjadi wadah fleksibel, yang akan membantu kita memusatkan ikon secara horizontal dan vertikal. Kami juga akan memperbarui warna latar belakang menjadi abu-abu yang sangat gelap dan warna ikon menjadi putih, untuk mendapatkan tampilan dan nuansa "mode gelap" yang ramping:

 body { display: flex; justify-content: center; align-items: center; background-color: #222; height: 100vh; }

Dengan itu, kami telah membuat tombol animasi yang berfungsi penuh menggunakan beberapa CSS dasar dan cuplikan JavaScript singkat. Sangat mudah untuk mengubah transformasi yang telah kita terapkan untuk membuat berbagai animasi. Pembaca dapat dengan mudah memotong CodePen—yang menyertakan sedikit CSS ekstra untuk memoles—dan menjadi kreatif.

Bekerja Dengan Data SVG Dari Editor Eksternal

Menu hamburger kami sangat sederhana. Bagaimana jika kita ingin membuat sesuatu yang lebih kompleks? Di situlah pengkodean SVG dengan tangan menjadi sulit dan perangkat lunak pengedit grafik vektor dapat membantu.

Animasi SVG kedua kami adalah tombol bisu yang menampilkan ikon headphone. Saat musik aktif, ikon akan berdenyut dan menari; ketika dimatikan, ikon akan dicoret:

Lihat tombol Pen Mute - 5 - coretan merah oleh Filip Defar (@dabrorius) di CodePen.

Ikon menggambar akan berada di luar cakupan tutorial ini (dan mungkin deskripsi pekerjaan Anda), jadi kita akan mulai dengan ikon SVG yang sudah digambar sebelumnya. Kami juga menginginkan penataan body yang sama seperti contoh menu hamburger kami.

Anda mungkin ingin membersihkan kode SVG sebelum bekerja dengannya. Anda dapat melakukannya dengan svgo, alat pengoptimal SVG berbasis Node.js sumber terbuka. Ini akan menghapus elemen yang tidak perlu dan membuat kode lebih mudah untuk diedit dengan tangan, yang perlu Anda lakukan untuk menambahkan kelas dan menggabungkan elemen yang berbeda.

Ikon SVG yang dibuat dalam perangkat lunak pengedit gambar tidak mungkin menggunakan unit relatif. Selain itu, kami ingin memastikan bahwa rasio aspek ikon dipertahankan, terlepas dari rasio aspek elemen SVG yang memuatnya. Untuk memungkinkan tingkat kontrol ini, kita akan menggunakan atribut viewBox .

Sebaiknya ubah ukuran SVG sehingga viewBox dapat disetel ke beberapa nilai yang mudah digunakan. Dalam hal ini, saya telah mengubahnya menjadi viewBox yang berukuran 100 x 100 piksel.

Mari pastikan ikon berada di tengah dan berukuran tepat. Kami akan menerapkan kelas mute ke elemen SVG dasar kami dan kemudian menambahkan gaya CSS berikut:

 .mute { fill: white; width: 80px; height: 70px; cursor: pointer; }

Di sini, width sedikit lebih besar dari height untuk menghindari kliping selama rotasi animasi kita.

Titik Awal Animasi SVG kami

SVG sekarang-bersih berisi satu elemen <g> yang berisi tiga elemen <path> .

Elemen path memungkinkan kita menggambar garis, kurva, dan busur. Paths dijelaskan dengan serangkaian perintah yang menjelaskan bagaimana bentuk harus digambar. Karena ikon kami terdiri dari tiga bentuk yang tidak terhubung, kami memiliki tiga jalur untuk menggambarkannya.

Elemen g SVG adalah wadah yang digunakan untuk mengelompokkan elemen SVG lainnya. Kami menggunakannya untuk menerapkan transformasi berdenyut dan menari di ketiga jalur secara bersamaan.

 <svg class="mute" viewBox="0 0 100 100"> <g> <path d="M92.6,50.075C92.213,26.775 73.25,7.938 50,7.938C26.75,7.938 7.775,26.775 7.388,50.075C3.112,51.363 -0.013,55.425 -0.013,60.25L-0.013,72.7C-0.013,78.55 4.575,83.3 10.238,83.3L18.363,83.3L18.363,51.6C18.4,51.338 18.438,51.075 18.438,50.813C18.438,33.275 32.6,19 50,19C67.4,19 81.563,33.275 81.563,50.813C81.563,51.088 81.6,51.338 81.638,51.6L81.638,83.313L89.763,83.313C95.413,83.313 100.013,78.563 100.013,72.713L100.013,60.263C100,55.438 96.875,51.362 92.6,50.075Z" /> <path d="M70.538,54.088L70.538,79.588C70.538,81.625 72.188,83.275 74.225,83.275L74.225,83.325L78.662,83.325L78.662,50.4L74.225,50.4C72.213,50.4 70.538,52.063 70.538,54.088Z" /> <path d="M25.75,50.4L21.313,50.4L21.313,83.325L25.75,83.325L25.75,83.275C27.788,83.275 29.438,81.625 29.438,79.588L29.438,54.088C29.45,52.063 27.775,50.4 25.75,50.4Z" /> </g> </svg>

Untuk membuat headphone berdenyut dan menari, transition tidak akan cukup. Ini adalah contoh yang cukup kompleks untuk membutuhkan keyframe.

Dalam hal ini, keyframe awal dan akhir kami (masing-masing pada 0% dan 100% animasi) menggunakan ikon headphone yang sedikit mengecil. Untuk 40% pertama dari animasi kami menumbuhkan gambar sedikit dan memiringkannya 5 derajat. Kemudian, untuk 40% animasi berikutnya, kami menurunkannya kembali ke 0,9x dan memutarnya 5 derajat ke sisi lain. Akhirnya, untuk 20% terakhir dari animasi, transformasi ikon kembali ke parameter awal yang sama untuk mengulang dengan lancar.

 @keyframes pulse { 0% { transform: scale(0.9); } 40% { transform: scale(1) rotate(5deg); } 80% { transform: scale(1) rotate(-5deg); } 100% { transform: scale(0.9) rotate(0); } }

Pengoptimalan Animasi CSS

Untuk menunjukkan cara kerja keyframe, kami membiarkan CSS keyframe kami lebih bertele-tele daripada yang seharusnya. Ada tiga cara kita bisa mempersingkatnya.

Karena keyframe 100% kami menetapkan seluruh daftar transform , jika kami menghilangkan rotate() seluruhnya, nilainya akan default ke 0:

 100% { transform: scale(0.9); }

Kedua, kita tahu kita ingin keyframe 0% dan 100% kita cocok karena kita mengulang animasi. Dengan mendefinisikannya dengan aturan CSS yang sama, kita tidak perlu mengingat untuk memodifikasi keduanya jika kita ingin mengubah titik bersama ini dalam loop animasi:

 0%, 100% { transform: scale(0.9); }

Terakhir, kita akan segera menerapkan transform: scale(0.9); ke kelas mute__headphones , dan ketika kita melakukannya, kita tidak perlu mendefinisikan keyframe awal dan akhir sama sekali! Mereka akan default ke gaya statis yang digunakan oleh mute__headphones .

Sekarang setelah kita mendefinisikan keyframe animasi, kita dapat menerapkan animasi. Kami menambahkan kelas .mute__headphones ke elemen <g> sehingga memengaruhi ketiga bagian ikon headphone. Pertama, kita sekali lagi mengatur transform-origin ke center karena kita ingin ikon berputar di sekitar pusatnya. Kami juga menskalakannya sehingga ukurannya cocok dengan bingkai utama animasi awal. Tanpa langkah ini, beralih dari ikon statis "dibisukan" ke ikon animasi akan selalu menghasilkan lompatan ukuran yang tiba-tiba. (Bagaimanapun, beralih kembali ke tidak bersuara akan menyebabkan lonjakan skala—dan kemungkinan rotasi juga—jika pengguna mengklik saat skala lebih besar dari 0,9x. Kami tidak dapat berbuat banyak tentang efek itu hanya dengan CSS.)

Kami menerapkan animasi menggunakan properti CSS animation tetapi hanya ketika kelas induk .is-active hadir, mirip dengan cara kami menganimasikan menu hamburger kami.

 .mute__headphones { transform-origin: center; transform: scale(0.9); } .is-active .mute__headphones { animation: pulse 2s infinite; }

JavaScript yang kita butuhkan untuk memungkinkan kita beralih antar status mengikuti pola yang sama seperti menu hamburger juga:

 const muteButton = document.querySelector(".mute"); muteButton.addEventListener("click", () => { muteButton.classList.toggle("is-active"); });

Bagian berikutnya yang akan kita tambahkan adalah garis coret yang muncul saat ikon tidak aktif. Karena ini adalah elemen desain yang sederhana, kita dapat mengkodekannya secara manual. Di sinilah memiliki nilai viewBox yang sederhana dan masuk akal berguna. Kita tahu bahwa tepi kanvas berada pada 0 dan 100 sehingga mudah untuk menghitung posisi awal dan akhir untuk garis kita:

 <line x1="12" y1="12" x2="88" y2="88" class="mute__strikethrough" />

Mengubah Ukuran vs. Menggunakan Unit Relatif

Sebuah kasus dapat dibuat untuk menggunakan unit relatif daripada mengubah ukuran gambar. Ini berlaku dalam contoh kami karena kami hanya menambahkan garis SVG sederhana di atas ikon kami.

Dalam skenario dunia nyata, Anda mungkin ingin menggabungkan konten SVG yang lebih kompleks dari beberapa sumber berbeda. Di sinilah membuat semuanya menjadi ukuran yang seragam berguna, karena kita tidak bisa secara manual mengkodekan nilai relatif seperti yang kita lakukan pada contoh kita.

Karena kita menerapkan kelas secara langsung ke elemen <line> yang dicoret, kita dapat menatanya melalui CSS. Kami hanya perlu memastikan bahwa garis tidak terlihat saat ikon aktif:

 .mute__strikethrough { stroke: red; opacity: 0.8; stroke-width: 12px; } .is-active .mute__strikethrough { opacity: 0; }

Secara opsional, kita dapat menambahkan kelas .is-active langsung ke SVG. Ini akan membuat animasi mulai segera setelah halaman dimuat, jadi kami secara efektif mengubah status awal ikon dari non-animasi (dibisukan) menjadi animasi (tidak dibisukan).

Animasi SVG berbasis CSS Ada di Sini untuk Tetap

Kami hanya menggores permukaan teknik animasi CSS dan cara kerja viewports. Penting untuk mengetahui cara menulis kode SVG dengan tangan agar animasi sederhana tetap sederhana, tetapi penting juga untuk mengetahui bagaimana dan kapan menggunakan grafik yang dibuat dengan editor eksternal. Meskipun browser modern memungkinkan kami membuat animasi yang mengesankan hanya dengan menggunakan fungsionalitas bawaan, untuk kasus penggunaan (yang sangat) kompleks, pengembang mungkin ingin menjelajahi perpustakaan animasi seperti GSAP atau anime.js.

Animasi tidak harus disediakan untuk proyek yang mewah. Teknik animasi CSS modern memungkinkan kita untuk membuat beragam animasi yang menarik dan halus dengan cara yang sederhana dan kompatibel dengan lintas-browser.


Terima kasih khusus kepada Mike Zeballos untuk tinjauan teknis artikel ini!