10个Framer Motion动画案例,让你的网站活起来

10个Framer Motion动画案例,让你的网站活起来

关键词:Framer Motion、网页动画、交互设计、React库、用户体验、入场动画、悬停效果

摘要:在这个“颜值即正义”的互联网时代,网页动画早已从“加分项”变成“必选项”。Framer Motion作为React生态中最受欢迎的动画库,用简单代码就能实现丝滑交互。本文精选10个高频实用的动画案例,从页面加载到用户点击,覆盖90%常见场景,手把手教你用Framer Motion让网站“活起来”!


背景介绍

目的和范围

本文旨在帮助前端开发者快速掌握Framer Motion的核心用法,通过10个具体案例覆盖网页动画的主流场景。无论你是刚接触动画的新手,还是想优化现有交互的进阶者,都能找到可直接复用的解决方案。

预期读者

  • 熟悉React基础的前端开发者
  • 对网页动画感兴趣的UI/UX设计师
  • 想提升网站用户体验的独立开发者

文档结构概述

本文先通过“会动的积木”故事引入Framer Motion核心概念,再逐一解析10个经典案例(含代码+原理),最后总结实战技巧与未来趋势。

术语表(用“魔法道具”比喻理解)

术语比喻解释
motion组件会动的积木(如motion.div是会跳舞的盒子,motion.img是会翻转的图片)
initial动画起点(积木的“初始姿势”)
animate动画终点(积木要到达的“最终姿势”)
whileHover鼠标悬停触发器(相当于“摸一下积木就开始跳舞”的魔法)
transition动画节奏控制器(决定积木“慢慢走”还是“蹦蹦跳”到终点)
AnimatePresence元素离场监视器(当积木被“收进盒子”时,自动播放离场动画)

核心概念与联系:用“魔法积木”理解Framer Motion

故事引入:魔法积木屋的秘密

想象你有一间积木屋,里面的每块积木都会“听指令”跳舞:

  • 当你推开门(页面加载),积木从地面“飘”到桌面(入场动画);
  • 你摸一下红色积木(鼠标悬停),它会“蹦”起来再落回去(悬停动画);
  • 当你要收走蓝色积木(元素卸载),它会先转个圈再消失(离场动画)。

Framer Motion就像给积木屋的每块积木施了魔法,你只需要用简单的“咒语”(代码)告诉它们“从哪来”“到哪去”“怎么动”,剩下的魔法由它自动完成!

核心概念解释(像给小朋友讲魔法)

1. motion组件:会动的积木块
Framer Motion提供了一系列“会动”的HTML标签,比如motion.div(会动的盒子)、motion.button(会动的按钮)、motion.img(会动的图片)。它们和普通HTML标签用法一样,但多了控制动画的“魔法属性”。

类比:普通积木是木头做的,motion积木是“魔法木头”做的,能听懂“动起来”的指令。

2. initial & animate:动画的起点和终点
initial定义动画开始时的状态(比如透明度0、位置偏移),animate定义动画结束时的状态(透明度1、位置归位)。就像告诉魔法积木:“你先站在墙角(initial),然后走到桌子中间(animate)”。

类比:小朋友玩“木头人”游戏,initial是“准备姿势”,animate是“最终姿势”。

3. transition:动画的“性格”
transition控制动画的时长、缓动函数(ease)、延迟等,决定动画是“慢悠悠”还是“急匆匆”。比如设置type: "spring"(弹簧效果),动画会像弹簧一样有弹性。

类比:同样从A到B,有人走得慢(easeOut),有人跑两步跳一下(spring)。

4. whileHover/whileTap:触发魔法的开关
whileHover是鼠标悬停时触发动画,whileTap是手指点击(或鼠标点击)时触发。就像给积木装了“传感器”,只要摸一下(悬停)或按一下(点击),它就开始跳舞。

类比:小区的声控灯,发出声音(悬停/点击)就会亮(触发动画)。

核心概念关系:魔法积木的协作流程

当你想让一个按钮做“悬停弹跳”动画时,四个核心概念会这样合作:

  1. motion.button(会动的按钮积木)负责接收指令;
  2. initial告诉它“初始姿势”(比如scale:1,不放大);
  3. whileHover触发“悬停时的姿势”(比如scale:1.1,放大10%);
  4. transition规定“从初始到悬停”的变化节奏(比如duration:0.2,0.2秒完成,type:spring有弹性)。

就像指挥一个小朋友:“你站在这(initial),当有人摸你(whileHover),你就跳起来(scale:1.1),跳的时候要像弹簧一样有弹性(transition:spring)。”

核心原理示意图(专业版)

用户交互(悬停/点击) → 触发whileHover/whileTap → 计算initial到目标状态的差值 → transition控制插值过程 → 浏览器通过GPU加速渲染动画帧

Mermaid 流程图

graph TD
    A[用户操作] --> B{触发条件}
    B -->|悬停| C[whileHover]
    B -->|点击| D[whileTap]
    B -->|加载/卸载| E[initial/animate]
    C --> F[计算起始状态(initial)]
    D --> F
    E --> F
    F --> G[transition控制节奏]
    G --> H[GPU加速渲染]
    H --> I[用户看到动画]

10个实战案例:手把手教你写会动的代码

案例1:页面加载入场动画(淡入+缩放)

效果描述:页面加载时,标题从“透明+缩小”渐变为“不透明+正常大小”,给用户“内容正在出现”的提示。

代码实现

import { motion } from "framer-motion";

function HeroTitle() {
  return (
    <motion.h1
      initial={{ opacity: 0, scale: 0.8 }} // 初始状态:透明+缩小20%
      animate={{ opacity: 1, scale: 1 }}    // 最终状态:不透明+正常大小
      transition={{ duration: 0.5 }}       // 动画时长0.5秒,默认缓动easeInOut
    >
      欢迎来到魔法积木屋!
    </motion.h1>
  );
}

关键参数解析

  • initial:动画起点(未加载时的“隐藏状态”);
  • animate:动画终点(加载完成后的“显示状态”);
  • transition.duration:动画总时间,0.5秒足够自然。

应用场景:首屏标题、卡片列表、导航栏等需要“渐入”的元素。


案例2:悬停弹跳按钮(弹簧效果)

效果描述:鼠标悬停在按钮上时,按钮像弹簧一样“弹起”10%,鼠标移开后“弹回”,增加交互趣味性。

代码实现

<motion.button
  whileHover={{ scale: 1.1 }}  // 悬停时放大10%
  whileTap={{ scale: 0.95 }}   // 点击时略微缩小(模拟按压感)
  transition={{
    type: "spring",           // 弹簧类型,更有弹性
    stiffness: 300,           // 弹簧“硬度”,值越大回弹越快
    damping: 20               // 阻尼,值越大晃动越少
  }}
  style={{ padding: "10px 20px" }}
>
  点击领取魔法
</motion.button>

关键参数解析

  • type: "spring":相比线性动画,弹簧效果更符合物理直觉;
  • stiffness:想象成弹簧的“松紧”,300属于中等硬度,不会太“软”或太“硬”;
  • damping:控制弹簧的“晃动次数”,20能让动画快速停止,避免晃太久。

应用场景:主要操作按钮(如“立即购买”“提交表单”)、交互图标(如爱心点赞)。


案例3:卡片翻转交互(鼠标移入)

效果描述:鼠标悬停在卡片上时,卡片沿Y轴旋转180度,展示背面内容(如价格/详情),移开后旋转回来。

代码实现

const Card = () => {
  return (
    <motion.div
      whileHover={{ rotateY: 180 }}  // 悬停时Y轴旋转180度
      transition={{ duration: 0.6 }}
      style={{
        width: 200,
        height: 300,
        backgroundColor: "#fff",
        borderRadius: 10,
        display: "flex",
        justifyContent: "center",
        alignItems: "center",
        cursor: "pointer",
        transformStyle: "preserve-3d" // 关键!保留3D变换空间
      }}
    >
      {/* 正面内容 */}
      <motion.div
        initial={{ opacity: 1 }}
        animate={{ opacity: whileHover ? 0 : 1 }} // 悬停时正面消失
        style={{ position: "absolute", backfaceVisibility: "hidden" }} // 背面不可见
      >
        正面:点击查看详情
      </motion.div>
      
      {/* 背面内容 */}
      <motion.div
        initial={{ opacity: 0 }}
        animate={{ opacity: whileHover ? 1 : 0 }} // 悬停时背面显示
        style={{ position: "absolute", transform: "rotateY(180deg)", backfaceVisibility: "hidden" }}
      >
        背面:价格99元
      </motion.div>
    </motion.div>
  );
};

关键技巧

  • transformStyle: "preserve-3d":让子元素继承3D变换空间,否则翻转时背面会“贴”在卡片上;
  • backfaceVisibility: "hidden":隐藏元素背面(避免翻转时看到正面的“倒影”);
  • 通过opacity动画控制正背面内容的显隐,与旋转同步。

应用场景:产品展示卡片、信息卡片(如简历、项目介绍)。


案例4:滚动触发的渐显动画(ScrollTrigger)

效果描述:当用户滚动到某个元素(如服务列表)时,元素从底部“滑入”并渐显,引导用户注意力。

代码实现(需配合useScroll钩子):

import { motion, useScroll } from "framer-motion";

function ServiceCard() {
  const { scrollYProgress } = useScroll(); // 获取滚动进度(0-1)
  
  return (
    <motion.div
      // 根据滚动进度计算偏移量:当进度>0.2时开始动画
      transform={{
        y: scrollYProgress > 0.2 ? 0 : 50,  // 未滚动时Y偏移50px(下方)
        opacity: scrollYProgress > 0.2 ? 1 : 0
      }}
      transition={{ duration: 0.5 }}
      style={{ margin: "20px 0", padding: 20, backgroundColor: "#f0f0f0" }}
    >
      专业魔法教学服务
    </motion.div>
  );
}

进阶技巧

  • useScroll钩子需要包裹在ScrollContainer组件中(通常是页面根容器);
  • 可以通过startend参数自定义触发位置(如start: "top center"表示元素顶部到达视口中心时触发)。

应用场景:长页面中的分段内容(如About Us、服务列表、团队介绍)。


案例5:导航菜单展开/收起(高度过渡)

效果描述:点击“菜单”按钮时,隐藏的导航列表从高度0平滑展开到实际高度,关闭时收缩回去。

代码实现(需配合useStateAnimatePresence):

import { motion, AnimatePresence } from "framer-motion";
import { useState } from "react";

function MobileNav() {
  const [isOpen, setIsOpen] = useState(false);
  
  return (
    <div>
      <button onClick={() => setIsOpen(!isOpen)}>菜单</button>
      
      <AnimatePresence> {/* 监视子元素的挂载/卸载 */}
        {isOpen && (
          <motion.ul
            key="nav-menu"
            initial={{ height: 0 }}        // 初始高度0(隐藏)
            animate={{ height: "auto" }}   // 最终高度自动(展开)
            exit={{ height: 0 }}           // 卸载时收缩回0
            transition={{ duration: 0.3 }}
            style={{
              listStyle: "none",
              padding: 0,
              margin: "10px 0",
              backgroundColor: "#fff"
            }}
          >
            <li>首页</li>
            <li>产品</li>
            <li>关于</li>
          </motion.ul>
        )}
      </AnimatePresence>
    </div>
  );
}

关键组件

  • AnimatePresence:必须包裹在需要“入场/离场”动画的元素外,它会检测子元素的key变化,触发exit动画;
  • height: "auto":自动计算展开后的高度,无需手动设置具体数值(更灵活)。

应用场景:移动端导航菜单、折叠面板(Accordion)、下拉选择框。


案例6:图片轮播滑动切换(滑动手势)

效果描述:用户左右滑动图片时,当前图片向左滑出,下一张图片从右侧滑入,模拟原生App的轮播体验。

代码实现(简化版):

import { motion, useDrag } from "framer-motion";

function ImageCarousel() {
  const [currentIndex, setCurrentIndex] = useState(0);
  const images = ["img1.jpg", "img2.jpg", "img3.jpg"];
  
  const dragControls = useDrag(({ offset }) => {
    // 根据拖拽偏移量判断是否切换图片(简化逻辑)
    if (offset.x > 100) setCurrentIndex(Math.max(0, currentIndex - 1));    // 右滑(上一张)
    if (offset.x < -100) setCurrentIndex(Math.min(2, currentIndex + 1));  // 左滑(下一张)
  });

  return (
    <div style={{ overflow: "hidden", width: "100%" }}>
      {images.map((img, index) => (
        <motion.img
          key={img}
          src={img}
          style={{
            width: "100%",
            position: "absolute",
            top: 0,
            left: 0
          }}
          initial={{ x: index === currentIndex ? 0 : "100%" }} // 当前图居中,其他在右侧
          animate={{ x: index === currentIndex ? 0 : "100%" }}
          transition={{ type: "spring", stiffness: 150 }}
          {...dragControls} // 绑定拖拽事件
        />
      ))}
    </div>
  );
}

关键技巧

  • useDrag钩子:监听用户拖拽操作,获取偏移量(offset.x);
  • 图片定位为absolute:所有图片叠在一起,通过x位移控制显示哪一张;
  • 弹簧过渡(type: "spring"):模拟手指松开后的“回弹”效果。

应用场景:产品图轮播、广告位展示、摄影作品画廊。


案例7:表单输入焦点动画(输入框扩展)

效果描述:当用户点击输入框时,输入框宽度从80%扩展到100%,边框颜色变深,提升输入时的沉浸感。

代码实现

<motion.input
  initial={{ width: "80%", borderColor: "#ddd" }}
  whileFocus={{ width: "100%", borderColor: "#2196F3" }} // 聚焦时扩展+变色
  transition={{ duration: 0.3 }}
  placeholder="输入你的魔法咒语..."
  style={{
    padding: "10px",
    border: "2px solid",
    borderRadius: 5,
    outline: "none"
  }}
/>

细节优化

  • 同时动画widthborderColor:多属性同步变化更自然;
  • outline: "none":移除浏览器默认聚焦框,用自定义动画替代。

应用场景:登录/注册表单、搜索框、评论输入框。


案例8:购物车添加抛物线动画(商品“飞”入购物车)

效果描述:用户点击“加入购物车”按钮时,商品图片从按钮位置“飞”到页面右上角的购物车图标,模拟“添加成功”的反馈。

代码实现(需计算坐标):

import { motion, useRef, useSpring } from "framer-motion";

function AddToCartButton() {
  const [isAnimating, setIsAnimating] = useState(false);
  const buttonRef = useRef(null);   // 按钮DOM引用
  const cartRef = useRef(null);     // 购物车DOM引用
  const spring = useSpring();       // 弹簧动画控制器

  const handleAddToCart = () => {
    setIsAnimating(true);
    // 获取按钮和购物车的坐标
    const buttonRect = buttonRef.current.getBoundingClientRect();
    const cartRect = cartRef.current.getBoundingClientRect();
    
    // 计算偏移量(从按钮中心到购物车中心)
    const x = cartRect.left - buttonRect.left + (cartRect.width/2 - buttonRect.width/2);
    const y = cartRect.top - buttonRect.top + (cartRect.height/2 - buttonRect.height/2);
    
    // 触发弹簧动画
    spring.start({ x, y, onComplete: () => setIsAnimating(false) });
  };

  return (
    <div>
      {/* 购物车图标 */}
      <div ref={cartRef} style={{ position: "fixed", top: 20, right: 20 }}>🛒</div>
      
      {/* 添加按钮 */}
      <button ref={buttonRef} onClick={handleAddToCart}>加入购物车</button>
      
      {/* 动画元素(商品图片) */}
      {isAnimating && (
        <motion.img
          src="product.jpg"
          style={{
            position: "fixed",
            left: buttonRef.current?.getBoundingClientRect().left,
            top: buttonRef.current?.getBoundingClientRect().top,
            width: 50,
            height: 50,
            pointerEvents: "none"
          }}
          animate={{ x: spring.x, y: spring.y }}
          transition={{ type: "spring", mass: 0.5, damping: 10 }}
          onComplete={() => setIsAnimating(false)}
        />
      )}
    </div>
  );
}

关键步骤

  1. 使用getBoundingClientRect()获取按钮和购物车的位置;
  2. 计算动画元素的起始(按钮位置)和结束(购物车位置)坐标;
  3. 用弹簧动画(type: "spring")模拟“抛掷”效果,mass(质量)越小越轻,damping越小晃动越久。

应用场景:电商商品详情页、外卖点餐页、虚拟商品购买。


案例9:加载状态旋转进度条(无限循环)

效果描述:页面加载时,一个圆形进度条持续旋转,提示用户“内容正在加载”,避免用户等待时焦虑。

代码实现

<motion.div
  animate={{ rotate: 360 }}   // 无限旋转360度
  transition={{
    repeat: Infinity,         // 无限重复
    repeatType: "loop",       // 循环模式(也可设为"reverse"来回旋转)
    duration: 1.5,            // 每圈1.5秒
    ease: "linear"            // 线性缓动(旋转速度均匀)
  }}
  style={{
    width: 40,
    height: 40,
    border: "4px solid #f3f3f3",
    borderTop: "4px solid #3498db",
    borderRadius: "50%",
    margin: "20px auto"
  }}
/>

参数解析

  • repeat: Infinity:动画结束后无限重复;
  • ease: "linear":避免旋转时“卡顿”,保持匀速;
  • 边框样式:通过border-top设置高亮色,其他边框灰色,形成“加载环”效果。

应用场景:数据加载、文件上传、页面跳转等待。


案例10:模态框弹出与关闭(淡入+缩放)

效果描述:点击“查看详情”按钮时,模态框从中心“缩放+淡入”弹出;点击关闭按钮时,反向“缩放+淡出”消失。

代码实现(配合AnimatePresence):

import { motion, AnimatePresence } from "framer-motion";
import { useState } from "react";

function ProductModal() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <div>
      <button onClick={() => setIsOpen(true)}>查看详情</button>
      
      <AnimatePresence>
        {isOpen && (
          <motion.div
            key="modal"
            initial={{ opacity: 0, scale: 0.8 }} // 初始状态:透明+缩小
            animate={{ opacity: 1, scale: 1 }}    // 最终状态:不透明+正常
            exit={{ opacity: 0, scale: 0.8 }}     // 关闭时:透明+缩小
            transition={{ duration: 0.2 }}
            style={{
              position: "fixed",
              top: "50%",
              left: "50%",
              transform: "translate(-50%, -50%)",
              backgroundColor: "white",
              padding: 20,
              borderRadius: 10,
              boxShadow: "0 4px 15px rgba(0,0,0,0.2)",
              maxWidth: "90%",
              zIndex: 1000
            }}
          >
            <h2>商品详情</h2>
            <p>魔法积木套装,包含100块魔法积木...</p>
            <button onClick={() => setIsOpen(false)}>关闭</button>
          </motion.div>
        )}
      </AnimatePresence>
    </div>
  );
}

用户体验细节

  • boxShadow:添加阴影提升“浮层”感;
  • zIndex: 1000:确保模态框在最上层;
  • 入场/离场动画对称(initialexit相同),视觉更统一。

应用场景:详情展示、表单填写、确认对话框。


核心算法原理:Framer Motion的动画引擎

Framer Motion底层基于Web Animations API,通过以下步骤实现流畅动画:

  1. 状态计算:根据initialanimate的值,计算属性(如xopacityscale)的起始值和目标值;
  2. 插值运算:使用transition定义的缓动函数(如线性、easeInOut、弹簧),在起始值和目标值之间生成连续的中间值(插值);
  3. GPU加速:将动画属性(如transformopacity)标记为可GPU加速的属性,避免重排重绘,提升性能;
  4. 帧渲染:以60fps(每秒60帧)的速度渲染动画帧,确保视觉流畅。

数学模型示例(弹簧动画):
弹簧动画的位移随时间变化的公式为:
x ( t ) = e − d ⋅ t ⋅ A ⋅ cos ⁡ ( ω ⋅ t + ϕ ) x(t) = e^{-d \cdot t} \cdot A \cdot \cos(\omega \cdot t + \phi) x(t)=edtAcos(ωt+ϕ)
其中:

  • ( d ):阻尼系数(damping),控制振动衰减速度;
  • ( A ):初始振幅(stiffness影响振幅);
  • ( \omega ):角频率(由stiffnessmass计算);
  • ( \phi ):初始相位(通常为0)。

简单来说,弹簧动画会先“超过”目标值,再因阻尼逐渐稳定到目标位置,模拟真实弹簧的物理特性。


项目实战:用Framer Motion重构官网首屏动画

开发环境搭建

  1. 创建React项目:npx create-react-app framer-demo
  2. 安装Framer Motion:npm install framer-motion
  3. 启动开发服务器:npm start

源代码实现(首屏标题+卡片入场动画)

// src/App.js
import { motion, AnimatePresence } from "framer-motion";
import "./App.css";

function App() {
  return (
    <div className="App">
      {/* 首屏标题动画 */}
      <motion.h1
        initial={{ y: 50, opacity: 0 }} // 初始位置:下方50px+透明
        animate={{ y: 0, opacity: 1 }}   // 最终位置:归位+不透明
        transition={{ duration: 0.6, ease: "easeOut" }}
        className="hero-title"
      >
        魔法积木屋——会跳舞的网页
      </motion.h1>

      {/* 卡片列表动画 */}
      <div className="card-container">
        {[1, 2, 3].map((id) => (
          <motion.div
            key={id}
            initial={{ y: 50, opacity: 0 }}
            animate={{ y: 0, opacity: 1 }}
            transition={{ 
              duration: 0.6, 
              ease: "easeOut", 
              delay: id * 0.1  // 每个卡片延迟0.1秒(依次入场)
            }}
            className="card"
          >
            <h3>魔法卡片 {id}</h3>
            <p>点击探索更多魔法效果</p>
          </motion.div>
        ))}
      </div>
    </div>
  );
}

export default App;

代码解读与分析

  • 标题动画:通过y(垂直位移)和opacity(透明度)的组合,实现“从下往上渐显”的效果,ease: "easeOut"让动画结尾更柔和;
  • 卡片列表动画:每个卡片添加delay: id * 0.1,使它们按顺序入场(1号0秒延迟,2号0.1秒,3号0.2秒),形成“波浪式”动画,比同时入场更有层次感;
  • 性能优化:所有动画属性(yopacity)都是GPU加速属性,不会触发页面重排,保证流畅性。

实际应用场景总结

动画类型典型页面位置核心目标
入场动画首屏标题、卡片列表引导用户注意力,减少“空白感”
悬停/点击动画按钮、图标、卡片增强交互反馈,提升操作确认感
滚动触发动画长页面分段内容(About Us)随滚动节奏展示内容,避免信息过载
展开/收起动画导航菜单、折叠面板节省空间,保持界面简洁
离场动画模态框关闭、商品移除明确“元素消失”的过程,避免突兀

工具和资源推荐

  1. 官方文档Framer Motion Docs(包含完整API和示例);
  2. CodeSandbox模板Framer Motion Starter(直接在线调试案例);
  3. 缓动函数工具Easing Functions Cheat Sheet(查看各种缓动效果);
  4. 社区资源Framer Motion GitHub(提交问题/查看源码);
  5. 设计参考Awwwards(看优秀网站的动画设计)。

未来发展趋势与挑战

趋势1:与3D动画深度融合

随着WebGL和Three.js的普及,Framer Motion未来可能支持更复杂的3D变换(如绕X/Y/Z轴旋转、3D位移),结合3D模型实现更沉浸的交互。

趋势2:基于用户行为的智能动画

通过机器学习分析用户操作习惯(如滚动速度、点击位置),动态调整动画参数(如延迟时间、缓动类型),实现“个性化动画”。

挑战1:性能优化

虽然Framer Motion已做了GPU加速优化,但复杂动画(如成百上千个元素同时动)仍可能导致卡顿,需要开发者合理控制动画数量和复杂度。

挑战2:跨浏览器兼容

部分新特性(如useScroll钩子)依赖较新的浏览器API,需做好降级处理(如旧浏览器使用静态布局)。


总结:学到了什么?

核心概念回顾

  • motion组件:会动的HTML标签(如motion.div);
  • initial/animate:动画的起点和终点;
  • transition:控制动画节奏(时长、缓动、弹簧);
  • whileHover/whileTap:交互触发动画的开关;
  • AnimatePresence:管理元素离场动画。

概念关系回顾

Framer Motion通过“触发条件(悬停/加载)→ 定义状态(initial/animate)→ 控制节奏(transition)→ GPU渲染”的流程,将简单的属性设置转化为流畅的动画效果。就像给每个网页元素发了一张“动画通行证”,让它们能根据你的指令“跳舞”。


思考题:动动小脑筋

  1. 如何让案例1的入场动画“更有层次”?比如标题先动,卡片列表后动(提示:使用delay属性)。
  2. 案例2的悬停按钮,如何让它在“鼠标悬停时”先放大,“悬停一段时间后”再缩小(提示:使用whileHover的嵌套状态)?
  3. 案例10的模态框,如何添加“背景模糊”的过渡效果(提示:给背景div添加backdropFilter动画)?

附录:常见问题与解答

Q:Framer Motion和CSS动画有什么区别?
A:CSS动画需要手动写关键帧(@keyframes),复杂动画(如弹簧、拖拽)实现困难;Framer Motion提供了更简洁的API(如type: "spring"),且自动处理GPU加速,性能更优。

Q:动画卡顿怎么办?
A:检查是否动画了非GPU加速属性(如widthmargin),尽量使用transformopacity;减少同时动画的元素数量;使用motion组件的layout属性(自动处理布局变化动画)。

Q:如何在Vue/Angular中使用Framer Motion?
A:Framer Motion官方主要支持React,但社区有Vue适配版(如@vueuse/motion),Angular可通过自定义指令集成。


扩展阅读 & 参考资料

  • 《Framer Motion官方文档》:https://www.framer.com/motion/
  • 《Web动画权威指南》(书籍):深入理解Web Animations API原理;
  • 《CSS-Tricks动画教程》:https://css-tricks.com/almanac/properties/a/animation/
  • 《Framer Motion最佳实践》:https://www.smashingmagazine.com/2021/05/animations-framer-motion/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值