Mari kita lanjutkan dengan materi lebih lanjut mengenai *variants*, *gestures*, *drag*, dan *layout animations* di Framer Motion. Fitur-fitur ini memungkinkan Anda untuk membuat animasi kompleks dan interaktif dalam aplikasi React.
### 1. Variants: Mengelola Animasi Kompleks
`Variants` memungkinkan kita mendefinisikan animasi dalam beberapa state yang berbeda dan menerapkannya ke berbagai elemen dalam satu tempat. Fitur ini sangat berguna ketika kita memiliki beberapa elemen yang berbagi animasi yang serupa.
#### Contoh Menggunakan Variants
```jsx
import React from "react";
import { motion } from "framer-motion";
const containerVariants = {
visible: {
opacity: 1,
transition: { staggerChildren: 0.3 }, // Mengatur jeda animasi anak
},
hidden: { opacity: 0 },
};
const itemVariants = {
visible: { opacity: 1, x: 0 },
hidden: { opacity: 0, x: -50 },
};
function VariantsExample() {
return (
<motion.ul
variants={containerVariants}
initial="hidden"
animate="visible"
style={{ listStyle: "none", padding: 0 }}
>
{[1, 2, 3].map((item) => (
<motion.li
key={item}
variants={itemVariants}
style={{
marginBottom: 10,
padding: 10,
backgroundColor: "lightcoral",
}}
>
Item {item}
</motion.li>
))}
</motion.ul>
);
}
export default VariantsExample;
Penjelasan:
- `containerVariants` memiliki animasi `staggerChildren` untuk mengatur jeda animasi di antara elemen anak.
- `itemVariants` mendefinisikan animasi individual untuk setiap item dengan transisi opacity dan posisi `x`.
### 2. Gestur (Hover, Tap, dan Drag)
Framer Motion memungkinkan kita menambahkan animasi responsif terhadap *gestures* seperti hover, tap, dan drag untuk memperkaya interaksi.
#### Hover dan Tap Animation
Animasi `whileHover` dan `whileTap` memungkinkan kita menambahkan animasi saat pengguna mengarahkan kursor atau menekan elemen.
```jsx
import { motion } from "framer-motion";
function GestureExample() {
return (
<motion.div
whileHover={{ scale: 1.1, rotate: 10 }} // Membesarkan dan memutar saat hover
whileTap={{ scale: 0.9 }} // Mengecilkan saat ditekan
style={{ width: 100, height: 100, backgroundColor: "gold" }}
/>
);
}
export default GestureExample;
Di sini:
- `whileHover` memberikan efek memperbesar dan memutar.
- `whileTap` membuat elemen sedikit mengecil saat ditekan, memberi kesan responsif.
### 3. Drag Animations
Animasi *drag* di Framer Motion memungkinkan elemen bisa ditarik atau digeser oleh pengguna. Kita bisa mengatur batas *drag*, *axis* (sumbu X/Y), dan juga memberikan animasi khusus saat elemen dilepas.
#### Contoh Dasar Drag
```jsx
import { motion } from "framer-motion";
function DraggableBox() {
return (
<motion.div
drag
dragConstraints={{ left: -100, right: 100, top: -50, bottom: 50 }}
style={{
width: 100,
height: 100,
backgroundColor: "skyblue",
}}
/>
);
}
export default DraggableBox;
Penjelasan:
- `drag` mengaktifkan fungsi drag.
- `dragConstraints` menentukan batas area yang bisa dijelajahi elemen dalam sumbu X dan Y.
#### Contoh Drag dengan Animasi
Anda bisa menambahkan animasi untuk saat elemen dilepas (drag-end) menggunakan `whileDrag` atau `onDragEnd`.
```jsx
import { motion } from "framer-motion";
function BouncyDraggableBox() {
return (
<motion.div
drag
whileDrag={{ scale: 1.2 }}
dragConstraints={{ left: -200, right: 200 }}
style={{
width: 100,
height: 100,
backgroundColor: "salmon",
borderRadius: "10px",
}}
/>
);
}
export default BouncyDraggableBox;
Pada kode ini:
- `whileDrag={{ scale: 1.2 }}` menambah efek pembesaran saat elemen sedang digeser.
### 4. Layout Animations: Animasi pada Perubahan Layout
Framer Motion mendukung *layout animations*, yaitu animasi yang otomatis mengikuti perubahan posisi atau ukuran elemen saat state komponen berubah.
#### Contoh Layout Animation
```jsx
import React, { useState } from "react";
import { motion } from "framer-motion";
function LayoutAnimation() {
const [isExpanded, setIsExpanded] = useState(false);
return (
<motion.div
layout
onClick={() => setIsExpanded(!isExpanded)}
style={{
width: 200,
height: isExpanded ? 200 : 100,
backgroundColor: "lightgreen",
borderRadius: "10px",
cursor: "pointer",
}}
>
<p style={{ padding: 20 }}>Click to {isExpanded ? "shrink" : "expand"}</p>
</motion.div>
);
}
export default LayoutAnimation;
Pada contoh di atas:
- `layout` memberi tahu Framer Motion untuk mengatur ulang ukuran atau posisi elemen berdasarkan state (`isExpanded`).
- Saat kotak diklik, ukurannya berubah dari 100px menjadi 200px, dengan animasi yang halus.
### 5. Layout Id: Animasi Transisi Antar Elemen dengan ID Layout
Jika Anda ingin membuat animasi transisi antar elemen yang sama di lokasi berbeda, gunakan `layoutId`. Ini memungkinkan elemen berpindah secara halus dari satu posisi ke posisi lain.
#### Contoh Menggunakan Layout ID
```jsx
import React, { useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
function SharedLayoutIdExample() {
const [isVisible, setIsVisible] = useState(true);
return (
<div onClick={() => setIsVisible(!isVisible)} style={{ cursor: "pointer" }}>
<AnimatePresence>
{isVisible ? (
<motion.div
key="box"
layoutId="shared-box"
style={{
width: 100,
height: 100,
backgroundColor: "purple",
marginBottom: 20,
}}
/>
) : (
<motion.div
key="expanded-box"
layoutId="shared-box"
style={{
width: 200,
height: 200,
backgroundColor: "purple",
}}
/>
)}
</AnimatePresence>
</div>
);
}
export default SharedLayoutIdExample;
Di sini:
- `layoutId="shared-box"` memastikan bahwa elemen yang sama akan berpindah tempat dengan animasi transisi yang mulus, meskipun ukuran atau posisinya berubah.
### Kesimpulan
Dengan menggunakan fitur-fitur ini, Anda bisa membuat animasi yang lebih kompleks dan interaktif:
- `Variants` memungkinkan animasi yang lebih terorganisir untuk berbagai elemen.
- `Gestures` (hover, tap, drag) memungkinkan interaksi yang responsif.
- `Drag` mengaktifkan pergerakan dinamis, sangat cocok untuk elemen yang perlu digeser.
- `Layout Animations` otomatis menyesuaikan posisi dan ukuran saat layout berubah.
- `Layout Id` memungkinkan transisi antar elemen dengan ID yang sama, ideal untuk animasi transisi antar halaman atau komponen.
Semua fitur ini menjadikan Framer Motion alat yang kuat untuk menciptakan antarmuka pengguna yang kaya dan menarik di aplikasi React Anda.