Animation Designer Skill
I help you create smooth, professional animations for web applications using Framer Motion and CSS.
What I Do
UI Animations:
Page transitions Component enter/exit animations Hover effects, button interactions Loading animations
Scroll Animations:
Parallax effects Scroll-triggered animations Progress indicators
Micro-interactions:
Button press feedback Form field focus states Success/error animations Drag and drop feedback Framer Motion Basics Installation npm install framer-motion
Basic Animation import { motion } from 'framer-motion'
export function FadeIn({ children }: { children: React.ReactNode }) {
return (
Common Animation Patterns Pattern 1: Fade In on Mount import { motion } from 'framer-motion'
export function Card({ children }: { children: React.ReactNode }) {
return (
Pattern 2: Staggered List Animation import { motion } from 'framer-motion'
const container = { hidden: { opacity: 0 }, show: { opacity: 1, transition: { staggerChildren: 0.1 } } }
const item = { hidden: { opacity: 0, y: 20 }, show: { opacity: 1, y: 0 } }
export function List({ items }: { items: string[] }) {
return (
Pattern 3: Button Hover Animation import { motion } from 'framer-motion'
export function AnimatedButton({ children, onClick }: {
children: React.ReactNode
onClick: () => void
}) {
return (
Pattern 4: Modal / Dialog Animation import { motion, AnimatePresence } from 'framer-motion'
export function Modal({ isOpen, onClose, children }: {
isOpen: boolean
onClose: () => void
children: React.ReactNode
}) {
return (
{/* Modal */}
<motion.div
initial={{ opacity: 0, scale: 0.9, y: 20 }}
animate={{ opacity: 1, scale: 1, y: 0 }}
exit={{ opacity: 0, scale: 0.9, y: 20 }}
transition={{ type: 'spring', damping: 25, stiffness: 300 }}
className="fixed inset-0 flex items-center justify-center z-50 p-4"
>
<div className="bg-white rounded-lg p-6 max-w-md w-full">
{children}
</div>
</motion.div>
</>
)}
</AnimatePresence>
) }
Pattern 5: Page Transition 'use client' import { motion } from 'framer-motion' import { usePathname } from 'next/navigation'
export function PageTransition({ children }: { children: React.ReactNode }) { const pathname = usePathname()
return (
// Usage in layout
export default function Layout({ children }) {
return (
Scroll Animations Scroll-Triggered Animation import { motion, useScroll, useTransform } from 'framer-motion' import { useRef } from 'react'
export function ScrollReveal({ children }: { children: React.ReactNode }) { const ref = useRef(null) const { scrollYProgress } = useScroll({ target: ref, offset: ['start end', 'end start'] })
const opacity = useTransform(scrollYProgress, [0, 0.3, 0.7, 1], [0, 1, 1, 0]) const y = useTransform(scrollYProgress, [0, 0.3, 0.7, 1], [100, 0, 0, -100])
return (
Parallax Effect import { motion, useScroll, useTransform } from 'framer-motion'
export function ParallaxSection() { const { scrollY } = useScroll() const y = useTransform(scrollY, [0, 500], [0, 150])
return (
<div className="relative z-10 flex items-center justify-center h-full">
<h1 className="text-6xl font-bold text-white">
Parallax Effect
</h1>
</div>
</div>
) }
Scroll Progress Indicator import { motion, useScroll } from 'framer-motion'
export function ScrollProgress() { const { scrollYProgress } = useScroll()
return (
Loading Animations Spinner import { motion } from 'framer-motion'
export function Spinner() {
return (
Skeleton Loader import { motion } from 'framer-motion'
export function SkeletonLoader() {
return (
Pulsing Dots import { motion } from 'framer-motion'
const dotVariants = { start: { scale: 0.8, opacity: 0.5 }, end: { scale: 1.2, opacity: 1 } }
export function PulsingDots() { return (
CSS Animations Keyframe Animations / Fade in animation / @keyframes fadeIn { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } }
.fade-in { animation: fadeIn 0.5s ease-out; }
/ Slide in from right / @keyframes slideInRight { from { transform: translateX(100%); } to { transform: translateX(0); } }
.slide-in-right { animation: slideInRight 0.3s ease-out; }
/ Bounce / @keyframes bounce { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-10px); } }
.bounce { animation: bounce 0.5s ease-in-out infinite; }
Tailwind Animations // tailwind.config.js module.exports = { theme: { extend: { keyframes: { 'fade-in': { '0%': { opacity: '0', transform: 'translateY(10px)' }, '100%': { opacity: '1', transform: 'translateY(0)' } }, 'slide-in': { '0%': { transform: 'translateX(-100%)' }, '100%': { transform: 'translateX(0)' } } }, animation: { 'fade-in': 'fade-in 0.5s ease-out', 'slide-in': 'slide-in 0.3s ease-out' } } } }
Usage:
Micro-Interactions Success Checkmark Animation import { motion } from 'framer-motion'
export function SuccessCheckmark() {
return (
Notification Badge import { motion } from 'framer-motion'
export function NotificationBadge({ count }: { count: number }) { return (
{count > 0 && (
<motion.div
initial={{ scale: 0 }}
animate={{ scale: 1 }}
transition={{ type: 'spring', stiffness: 500, damping: 15 }}
className="absolute -top-1 -right-1 bg-red-600 text-white text-xs rounded-full w-5 h-5 flex items-center justify-center"
>
{count}
</motion.div>
)}
</div>
) }
Animation Best Practices
1. Performance
// ✅ Good: Animate transform and opacity (GPU accelerated)
// ❌ Bad: Animate width, height (triggers layout)
- Duration // Too fast: < 100ms (feels abrupt) // Too slow: > 500ms (feels sluggish)
// ✅ Sweet spot: 200-400ms for most UI animations
- Easing
// Natural motion: easeOut (starts fast, ends slow)
// Bouncy: spring
- Reduce Motion (Accessibility) import { useReducedMotion } from 'framer-motion'
export function AccessibleAnimation({ children }: { children: React.ReactNode }) { const shouldReduceMotion = useReducedMotion()
return (
Complex Animations Drag and Drop import { motion } from 'framer-motion' import { useState } from 'react'
export function Draggable() { const [position, setPosition] = useState({ x: 0, y: 0 })
return (
Animated Number Counter import { motion, useSpring, useTransform } from 'framer-motion' import { useEffect } from 'react'
export function AnimatedNumber({ value }: { value: number }) { const spring = useSpring(0, { stiffness: 100, damping: 30 }) const display = useTransform(spring, (current) => Math.round(current).toLocaleString() )
useEffect(() => { spring.set(value) }, [spring, value])
return
// Usage
When to Use Me
Perfect for:
Creating polished UI animations Building interactive components Adding scroll effects Designing loading states Improving user feedback
I'll help you:
Choose the right animation type Implement smooth transitions Optimize animation performance Ensure accessibility Create delightful micro-interactions What I'll Create ✨ Page Transitions 🎯 Micro-Interactions 📜 Scroll Animations ⏳ Loading States 🎨 Hover Effects 🎪 Complex Animations
Let's make your interfaces feel alive!
← 返回排行榜