Framer Motion 动画不损害性能:模式与陷阱

发布: (2026年4月7日 GMT+8 16:55)
3 分钟阅读
原文: Dev.to

Source: Dev.to

黄金法则:仅对 Transform 和 Opacity 进行动画

// Bad — triggers layout recalculation (expensive)

// Good — GPU‑composited, no layout (cheap)

会触发布局的属性: width, height, top, left, padding, margin
不会触发布局的属性: x, y, scale, rotate, opacity, skew


进入动画

const fadeUp = {
  hidden: { opacity: 0, y: 24 },
  visible: {
    opacity: 1,
    y: 0,
    transition: { duration: 0.4, ease: 'easeOut' },
  },
};

function Card({ children }: { children: React.ReactNode }) {
  return (
    
      {children}
    
  );
}

viewport={{ once: true }} 非常关键——如果没有它,元素每次进入视口时都会重新触发动画。


子元素错位(Staggered Children)

const container = {
  hidden: {},
  visible: {
    transition: { staggerChildren: 0.1, delayChildren: 0.2 },
  },
};

const item = {
  hidden: { opacity: 0, y: 20 },
  visible: { opacity: 1, y: 0, transition: { duration: 0.3 } },
};

function ProductGrid({ products }: { products: Product[] }) {
  return (
    
      {products.map(product => (
        
          
        
      ))}
    
  );
}

悬停和点击状态

function Button({ children, onClick }: ButtonProps) {
  return (
    
      {children}
    
  );
}

弹簧物理效果比线性过渡在交互元素上更自然。


布局动画

function ExpandableCard({ title, content }: CardProps) {
  const [expanded, setExpanded] = useState(false);

  return (
     setExpanded(!expanded)}>
      {title}
      {expanded && (
        
          {content}
        
      )}
    
  );
}

layout 属性会自动为尺寸变化添加动画——无需显式地对宽度/高度进行动画处理。


使用 AnimatePresence 实现退出动画

import { AnimatePresence, motion } from 'framer-motion';

function Notifications({ notifications }: { notifications: Notification[] }) {
  return (
    
      {notifications.map(notification => (
        
          {notification.message}
        
      ))}
    
  );
}

如果不使用 AnimatePresence,元素会直接消失——没有退出动画。


性能技巧

// 1. Use style prop for non‑animating styles (skips motion overhead)

// 2. Disable animations for users who prefer reduced motion
import { useReducedMotion } from 'framer-motion';

function AnimatedCard() {
  const shouldReduce = useReducedMotion();
  return (
    
  );
}

// 3. Avoid animating hundreds of elements simultaneously
//    Cap stagger at ~20 items, virtualize the rest

AI SaaS Starter Kit 已预置 Framer Motion 动画在登录页和仪表盘上——全部使用 GPU 合成属性。一次性 $99。

0 浏览
Back to Blog

相关文章

阅读更多 »