### 1. Menggunakan Media Queries untuk Animasi Responsif
Framer Motion memungkinkan Anda untuk mengubah properti animasi berdasarkan ukuran layar atau kondisi perangkat. Salah satu pendekatannya adalah dengan memanfaatkan *custom hook* yang mendeteksi ukuran layar dan mengubah animasi sesuai kebutuhan.
#### Contoh Dasar Menggunakan Media Queries
Pertama, kita bisa membuat *custom hook* untuk mendeteksi lebar layar dan mengatur animasi berdasarkan hasilnya:
```jsx
import { useState, useEffect } from "react";
function useMediaQuery(query) {
const [matches, setMatches] = useState(window.matchMedia(query).matches);
useEffect(() => {
const media = window.matchMedia(query);
if (media.matches !== matches) {
setMatches(media.matches);
}
const listener = () => setMatches(media.matches);
media.addListener(listener);
return () => media.removeListener(listener);
}, [matches, query]);
return matches;
}
#### Menggunakan Media Query di Komponen Animasi
Dengan *hook* di atas, kita dapat menentukan animasi yang berbeda untuk perangkat mobile dan desktop:
```jsx
import React from "react";
import { motion } from "framer-motion";
function ResponsiveAnimation() {
const isMobile = useMediaQuery("(max-width: 768px)");
return (
<motion.div
animate={{
x: isMobile ? 0 : 100, // Animasi berdasarkan ukuran layar
scale: isMobile ? 1 : 1.2,
}}
transition={{ duration: 0.5 }}
style={{
width: 100,
height: 100,
backgroundColor: "tomato",
margin: "0 auto",
}}
/>
);
}
export default ResponsiveAnimation;
Di sini:
- `isMobile` mendeteksi apakah perangkat menggunakan layar berukuran 768px ke bawah.
- Jika layar berukuran kecil, elemen tidak bergerak (`x: 0`) dan tetap pada skala 1. Untuk layar lebih besar, elemen bergerak 100px ke kanan dengan skala 1.2.
### 2. Conditional Animation Menggunakan State atau Props
Untuk membuat animasi yang berubah-ubah berdasarkan kondisi tertentu, Anda bisa memanfaatkan *state* atau *props*. Ini sering digunakan untuk mengubah animasi saat pengguna berinteraksi, misalnya saat tombol ditekan atau area tertentu disentuh.
#### Contoh Animasi Berdasarkan State
```jsx
import React, { useState } from "react";
import { motion } from "framer-motion";
function ToggleScale() {
const [isToggled, setIsToggled] = useState(false);
return (
<div>
<button onClick={() => setIsToggled(!isToggled)}>Toggle Scale</button>
<motion.div
animate={{
scale: isToggled ? 1.5 : 1,
backgroundColor: isToggled ? "lightblue" : "coral",
}}
transition={{ duration: 0.5 }}
style={{
width: 100,
height: 100,
margin: "20px auto",
}}
/>
</div>
);
}
export default ToggleScale;
Di sini:
- Tombol *toggle* mengubah skala dan warna elemen dengan menggunakan `setIsToggled` untuk mengontrol animasi.
### 3. Menggunakan Variants untuk Kontrol Interaksi yang Lebih Terorganisir
`Variants` sangat membantu dalam mengatur animasi kompleks dan responsif, karena kita bisa mendefinisikan berbagai state dan menerapkan animasi secara terorganisir. Dengan variants, Anda bisa membuat *state* berbeda seperti `hover`, `tap`, atau `focus`.
#### Contoh Menggunakan Variants untuk Interaksi
```jsx
import React from "react";
import { motion } from "framer-motion";
const boxVariants = {
initial: { scale: 1, rotate: 0 },
hover: { scale: 1.1, rotate: 10 },
tap: { scale: 0.9, rotate: -10 },
};
function InteractiveBox() {
return (
<motion.div
variants={boxVariants}
initial="initial"
whileHover="hover"
whileTap="tap"
style={{
width: 100,
height: 100,
backgroundColor: "mediumseagreen",
margin: "0 auto",
}}
/>
);
}
export default InteractiveBox;
Pada kode ini:
- `boxVariants` mendefinisikan tiga state: `initial`, `hover`, dan `tap`.
- `whileHover` dan `whileTap` memicu perubahan skala dan rotasi saat elemen di-hover atau di-tap.
### 4. Drag and Drop Interaktif dengan Constraint Responsif
Jika elemen perlu digeser atau dipindahkan oleh pengguna, kita dapat menggunakan animasi drag dengan batas *drag constraints* responsif.
#### Contoh Drag dengan Constraints
```jsx
import { motion } from "framer-motion";
function ResponsiveDragBox() {
return (
<motion.div
drag
dragConstraints={{ left: -50, right: 50, top: -50, bottom: 50 }}
style={{
width: 100,
height: 100,
backgroundColor: "deepskyblue",
borderRadius: "10px",
margin: "0 auto",
}}
/>
);
}
export default ResponsiveDragBox;
Pada contoh ini:
- Batas drag dibuat lebih sempit, sehingga elemen hanya bisa bergerak dalam area tertentu.
### 5. Layout Animations yang Beradaptasi dengan Perubahan Ukuran Layar
*Layout animations* memungkinkan elemen beradaptasi saat ukuran atau posisi mereka berubah akibat perubahan layout. Ini bisa sangat membantu dalam aplikasi responsif, karena elemen bisa berpindah posisi dengan animasi transisi saat ukuran layar berubah.
#### Contoh Layout Animation pada Elemen yang Berpindah
```jsx
import React, { useState } from "react";
import { motion } from "framer-motion";
function ResponsiveLayoutAnimation() {
const [isToggled, setIsToggled] = useState(false);
return (
<div onClick={() => setIsToggled(!isToggled)} style={{ display: "flex", justifyContent: "center" }}>
<motion.div
layout
style={{
width: isToggled ? 200 : 100,
height: 100,
backgroundColor: isToggled ? "pink" : "lavender",
borderRadius: 10,
margin: "20px",
}}
/>
</div>
);
}
export default ResponsiveLayoutAnimation;
Pada contoh ini:
- Saat elemen diklik, ukurannya berubah dari 100px menjadi 200px, dan animasi transisi dilakukan dengan halus karena menggunakan `layout`.
### 6. Menggunakan `useMotionValue` dan `useTransform` untuk Kontrol yang Lebih Rinci
`useMotionValue` dan `useTransform` memberikan kontrol lebih rinci untuk mengelola animasi yang responsif dan interaktif. *Hook* ini memungkinkan Anda membuat animasi yang berubah secara dinamis sesuai dengan nilai tertentu, seperti posisi `x` atau `y` elemen.
#### Contoh Interaksi dengan Motion Value dan Transformasi
```jsx
import { motion, useMotionValue, useTransform } from "framer-motion";
function TransformExample() {
const x = useMotionValue(0);
const scale = useTransform(x, [-100, 100], [0.5, 1.5]);
return (
<motion.div
drag="x"
style={{
x,
scale,
width: 100,
height: 100,
backgroundColor: "gold",
borderRadius: "50%",
margin: "0 auto",
}}
/>
);
}
export default TransformExample;
Penjelasan:
- `useMotionValue` melacak posisi `x` elemen saat di-drag.
- `useTransform` mengubah nilai `scale` berdasarkan nilai `x`, menciptakan efek perbesaran dan pengecilan secara dinamis saat elemen digeser.
### Kesimpulan
Dengan menggunakan fitur-fitur di atas, Anda bisa membuat animasi yang responsif dan interaktif dengan Framer Motion, di antaranya:
- *Media queries* untuk menentukan animasi berbeda pada perangkat yang berbeda.
- *Conditional animation* menggunakan state atau props.
- *Variants* untuk mengatur berbagai *interaction state* seperti hover dan tap.
- *Drag and drop* dengan constraint yang dapat disesuaikan.
- *Layout animations* untuk penyesuaian otomatis pada perubahan layout.
- *Motion values* dan *transform* untuk kontrol animasi yang lebih rinci.
Ini membantu menciptakan UI yang kaya, fleksibel, dan adaptif, meningkatkan pengalaman pengguna di berbagai perangkat.