ui-animation

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

UI Animation & Motion Design

UI动画与动态设计

Comprehensive guide for creating purposeful, performant animations in user interfaces.
一份关于在用户界面中创建有意义、高性能动画的综合指南。

Animation Principles

动画原则

The 12 Principles of Animation (Applied to UI)

12项动画原则(UI领域应用)

PrincipleUI Application
TimingDuration reflects importance/distance
EasingNatural acceleration/deceleration
AnticipationVisual preparation for action
Follow-throughMomentum continues after stop
Secondary ActionSupporting elements respond
StagingDraw attention to key element
Squash & StretchBouncy, playful interactions
ExaggerationEmphasize important feedback
ArcNatural curved motion paths
OverlapElements move at different rates
Solid DrawingMaintain consistent 3D space
AppealEngaging, delightful motion
原则UI场景应用
Timing(时长)时长反映操作的重要性或元素移动距离
Easing(缓动)模拟自然的加速/减速效果
Anticipation(预备)为操作提供视觉准备提示
Follow-through(跟随)元素停止后保留动量的余效
Secondary Action(次要动作)辅助元素产生联动响应
Staging(聚焦)将用户注意力引导至关键元素
Squash & Stretch(挤压与拉伸)创造活泼、有趣的交互效果
Exaggeration(夸张)强调重要的反馈信息
Arc(弧线运动)采用自然的弧形运动路径
Overlap(重叠动画)元素以不同速率运动
Solid Drawing(空间一致性)保持一致的3D空间感
Appeal(吸引力)创造引人入胜、愉悦的动效体验

Why Animate?

为什么需要动画?

FUNCTIONAL PURPOSES:
✓ Guide attention to important changes
✓ Show relationships between elements
✓ Provide feedback for actions
✓ Communicate system status
✓ Ease cognitive load
✓ Create spatial orientation

NOT FOR:
✗ Pure decoration
✗ Showing off skills
✗ Making things "feel modern"
✗ Distracting from content

功能性用途:
✓ 引导用户关注重要变化
✓ 展示元素间的关联关系
✓ 为用户操作提供反馈
✓ 传达系统状态
✓ 降低认知负担
✓ 构建空间方位感

不适用于:
✗ 纯装饰性场景
✗ 单纯展示技术能力
✗ 只为追求“现代感”
✗ 分散用户对核心内容的注意力

Timing & Duration

时长与节奏

Duration Guidelines

时长参考指南

INSTANT (0-100ms):
└─→ Button state changes
└─→ Toggle switches
└─→ Micro-feedback

FAST (100-200ms):
└─→ Hover effects
└─→ Simple fades
└─→ Small movements

STANDARD (200-300ms):
└─→ Most UI transitions
└─→ Modal open/close
└─→ Dropdown menus

SLOW (300-500ms):
└─→ Complex transitions
└─→ Page transitions
└─→ Large element movement

DELIBERATE (500ms+):
└─→ Hero animations
└─→ Skeleton loading
└─→ Onboarding sequences
即时(0-100ms):
└─→ 按钮状态切换
└─→ 开关控件切换
└─→ 微型反馈效果

快速(100-200ms):
└─→ 悬停效果
└─→ 简单淡入淡出
└─→ 小范围元素移动

标准(200-300ms):
└─→ 大多数UI过渡效果
└─→ 模态框打开/关闭
└─→ 下拉菜单展开/收起

缓慢(300-500ms):
└─→ 复杂过渡效果
└─→ 页面切换
└─→ 大范围元素移动

刻意延迟(500ms以上):
└─→ 首屏英雄区动画
└─→ 骨架屏加载
└─→ 新手引导流程

Distance-Based Timing

基于距离的时长计算

Rule: Longer distance = Longer duration

Small (< 100px):   150-200ms
Medium (100-300px): 200-300ms
Large (300-500px):  300-400ms
Full screen:        400-500ms

Formula:
duration = baseTime + (distance × factor)

规则:移动距离越长,动画时长越久

小距离(< 100px): 150-200ms
中距离(100-300px):200-300ms
大距离(300-500px):300-400ms
全屏移动:        400-500ms

计算公式:
duration = baseTime + (distance × factor)

Easing Functions

缓动函数

Standard Easings

标准缓动类型

LINEAR
├────────────────────────────┤
Constant speed. Rarely natural.
Use: Progress bars, clock hands

EASE-OUT (Deceleration)
├═══════════────────────────┤
Fast start, slow end.
Use: Elements entering the screen

EASE-IN (Acceleration)
├────────────────═══════════┤
Slow start, fast end.
Use: Elements leaving the screen

EASE-IN-OUT (S-curve)
├────═══════════════────────┤
Slow start and end, fast middle.
Use: On-screen transitions

EASE-OUT-BACK (Overshoot)
├═══════════────────────╗───┤
Overshoots, settles back.
Use: Playful entrances, bounces
LINEAR(线性)
├────────────────────────────┤
匀速运动,很少符合自然规律。
适用场景:进度条、时钟指针

EASE-OUT(减速)
├═══════════────────────────┤
快速启动,缓慢结束。
适用场景:元素进入屏幕

EASE-IN(加速)
├────────────────═══════════┤
缓慢启动,快速结束。
适用场景:元素离开屏幕

EASE-IN-OUT(S曲线)
├────═══════════════────────┤
缓慢启动和结束,中间快速运动。
适用场景:屏幕内元素状态过渡

EASE-OUT-BACK(回弹)
├═══════════────────────╗───┤
元素超出目标位置后回弹复位。
适用场景:活泼的入场动画、弹跳效果

CSS Easing Values

CSS缓动值

css
/* Built-in keywords */
linear: cubic-bezier(0, 0, 1, 1)
ease: cubic-bezier(0.25, 0.1, 0.25, 1)
ease-in: cubic-bezier(0.42, 0, 1, 1)
ease-out: cubic-bezier(0, 0, 0.58, 1)
ease-in-out: cubic-bezier(0.42, 0, 0.58, 1)

/* Material Design standard */
standard: cubic-bezier(0.4, 0, 0.2, 1)
decelerate: cubic-bezier(0, 0, 0.2, 1)
accelerate: cubic-bezier(0.4, 0, 1, 1)

/* Custom: Snappy */
snappy: cubic-bezier(0.5, 0, 0, 1)

/* Custom: Bouncy */
bouncy: cubic-bezier(0.68, -0.55, 0.27, 1.55)

/* Spring-like (use JS libraries) */
spring: { stiffness: 300, damping: 20 }
css
/* 内置关键字 */
linear: cubic-bezier(0, 0, 1, 1)
ease: cubic-bezier(0.25, 0.1, 0.25, 1)
ease-in: cubic-bezier(0.42, 0, 1, 1)
ease-out: cubic-bezier(0, 0, 0.58, 1)
ease-in-out: cubic-bezier(0.42, 0, 0.58, 1)

/* Material Design标准 */
standard: cubic-bezier(0.4, 0, 0.2, 1)
decelerate: cubic-bezier(0, 0, 0.2, 1)
accelerate: cubic-bezier(0.4, 0, 1, 1)

/* 自定义:敏捷型 */
snappy: cubic-bezier(0.5, 0, 0, 1)

/* 自定义:弹跳型 */
bouncy: cubic-bezier(0.68, -0.55, 0.27, 1.55)

/* 弹簧效果(需使用JS库) */
spring: { stiffness: 300, damping: 20 }

When to Use Each

场景适配建议

ScenarioEasingWhy
Element enteringease-outArrives energetically, settles
Element leavingease-inGathers momentum to exit
On-screen changeease-in-outSmooth state change
Attention grabbingbounce/springPlayful, noticeable
Background/subtleease-outUnobtrusive

场景缓动类型原因说明
元素入场ease-out充满活力地到达目标位置后平稳过渡
元素离场ease-in逐渐积累动量后离开屏幕
屏幕内状态变化ease-in-out平滑的状态切换体验
需要吸引注意力bounce/spring活泼醒目,容易引起关注
背景/细微效果ease-out不干扰用户核心操作

Animation Patterns

动画模式

Micro-interactions

微交互

BUTTON STATES:
┌─────────────────────────────────────────┐
│ Rest → Hover: scale(1.02), 100ms        │
│ Hover → Active: scale(0.98), 50ms       │
│ Active → Rest: scale(1), 150ms ease-out │
└─────────────────────────────────────────┘

TOGGLE SWITCH:
┌─────────────────────────────────────────┐
│ Thumb: translateX, 200ms ease-out       │
│ Track: background-color, 200ms          │
│ State: slight bounce at end             │
└─────────────────────────────────────────┘

CHECKBOX:
┌─────────────────────────────────────────┐
│ Check mark: stroke-dashoffset animation │
│ Background: scale from center, 150ms    │
│ Ripple: expanding circle, 300ms         │
└─────────────────────────────────────────┘
按钮状态变化:
┌─────────────────────────────────────────┐
│ 常态 → 悬停:scale(1.02),100ms        │
│ 悬停 → 激活:scale(0.98),50ms       │
│ 激活 → 常态:scale(1),150ms ease-out │
└─────────────────────────────────────────┘

开关控件:
┌─────────────────────────────────────────┐
│ 滑块:translateX,200ms ease-out       │
│ 轨道:background-color,200ms          │
│ 状态切换:结束时轻微回弹             │
└─────────────────────────────────────────┘

复选框:
┌─────────────────────────────────────────┐
│ 勾选标记:stroke-dashoffset动画效果 │
│ 背景:从中心缩放,150ms             │
│ 波纹:扩散圆形效果,300ms           │
└─────────────────────────────────────────┘

Loading States

加载状态

SKELETON SCREENS:
┌──────────────────────────┐
│ ▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░  │ Shimmer effect
│ ▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░  │ Linear gradient
│ ▓▓▓▓▓▓░░░░░░░░░░░░░░░░  │ Moving left to right
└──────────────────────────┘

CSS:
background: linear-gradient(
  90deg,
  #f0f0f0 25%,
  #e0e0e0 50%,
  #f0f0f0 75%
);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;

SPINNER:
- Duration: 1-2 seconds per rotation
- Easing: linear (consistent motion)
- Style: Match brand identity
骨架屏:
┌──────────────────────────┐
│ ▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░  │ 微光效果
│ ▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░  │ 线性渐变
│ ▓▓▓▓▓▓░░░░░░░░░░░░░░░░  │ 从左向右移动
└──────────────────────────┘

CSS代码:
background: linear-gradient(
  90deg,
  #f0f0f0 25%,
  #e0e0e0 50%,
  #f0f0f0 75%
);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;

加载旋转器:
- 时长:每旋转1-2秒
- 缓动:linear(匀速运动)
- 风格:匹配品牌视觉

Page Transitions

页面过渡

CROSSFADE:
├──────────────────────────────────────────┤
│ Old page: opacity 1 → 0, 200ms           │
│ New page: opacity 0 → 1, 200ms           │
│ Timing: Sequential or overlapping        │
└──────────────────────────────────────────┘

SLIDE:
├──────────────────────────────────────────┤
│ Direction follows navigation hierarchy   │
│ Forward: Slide left (new from right)     │
│ Back: Slide right (prev from left)       │
│ Duration: 300-400ms                      │
└──────────────────────────────────────────┘

SHARED ELEMENT:
├──────────────────────────────────────────┤
│ Element morphs between states            │
│ Position, size, border-radius change     │
│ Creates continuity between screens       │
│ Duration: 300-500ms                      │
└──────────────────────────────────────────┘
交叉淡入淡出:
├──────────────────────────────────────────┤
│ 旧页面:opacity从1→0,200ms           │
│ 新页面:opacity从0→1,200ms           │
│ 时序:可顺序执行或重叠执行        │
└──────────────────────────────────────────┘

滑动过渡:
├──────────────────────────────────────────┤
│ 方向遵循导航层级逻辑   │
│ 前进:向左滑动(新页面从右侧进入)     │
│ 返回:向右滑动(上一页从左侧进入)       │
│ 时长:300-400ms                      │
└──────────────────────────────────────────┘

共享元素过渡:
├──────────────────────────────────────────┤
│ 元素在不同状态间变形过渡            │
│ 位置、尺寸、圆角属性变化     │
│ 在不同页面间创造视觉连续性       │
│ 时长:300-500ms                      │
└──────────────────────────────────────────┘

List Animations

列表动画

STAGGERED ENTRANCE:
┌─ Item 1 ────────────────┐  delay: 0ms
├─ Item 2 ────────────────┤  delay: 50ms
├─ Item 3 ────────────────┤  delay: 100ms
├─ Item 4 ────────────────┤  delay: 150ms
└─ Item 5 ────────────────┘  delay: 200ms

Max total duration: 500ms
Stagger: 30-50ms per item
Animation: translateY + opacity

REORDER:
- Use FLIP technique
- Duration: 200-300ms
- Ease: ease-out

 stagger入场:
┌─ 项1 ────────────────┐  延迟:0ms
├─ 项2 ────────────────┤  延迟:50ms
├─ 项3 ────────────────┤  延迟:100ms
├─ 项4 ────────────────┤  延迟:150ms
└─ 项5 ────────────────┘  延迟:200ms

总时长上限:500ms
 stagger间隔:30-50ms每一项
动画效果:translateY + opacity

重排动画:
- 使用FLIP技术
- 时长:200-300ms
- 缓动:ease-out

Performance

性能优化

GPU-Accelerated Properties

GPU加速属性

FAST (Compositor only):
✓ transform: translate, scale, rotate
✓ opacity
✓ filter (with will-change)

SLOW (Triggers layout/paint):
✗ width, height
✗ margin, padding
✗ top, left, right, bottom
✗ border, border-radius
✗ font-size
✗ box-shadow (repaints)

OPTIMIZATION:
will-change: transform, opacity;
/* Use sparingly! */
高效(仅需合成器处理):
✓ transform: translate、scale、rotate
✓ opacity
✓ filter(配合will-change)

低效(触发布局/重绘):
✗ width、height
✗ margin、padding
✗ top、left、right、bottom
✗ border、border-radius
✗ font-size
✗ box-shadow(导致重绘)

优化技巧:
will-change: transform, opacity;
/* 请谨慎使用! */

Performance Guidelines

性能优化指南

css
/* Good: GPU-accelerated */
.animated-element {
  transform: translateX(0);
  transition: transform 300ms ease-out;
}
.animated-element.moved {
  transform: translateX(100px);
}

/* Bad: Layout thrashing */
.animated-element {
  left: 0;
  transition: left 300ms ease-out;
}
.animated-element.moved {
  left: 100px;
}
css
/* 推荐:GPU加速 */
.animated-element {
  transform: translateX(0);
  transition: transform 300ms ease-out;
}
.animated-element.moved {
  transform: translateX(100px);
}

/* 不推荐:布局抖动 */
.animated-element {
  left: 0;
  transition: left 300ms ease-out;
}
.animated-element.moved {
  left: 100px;
}

FLIP Technique

FLIP技术

javascript
// First: Get initial position
const first = element.getBoundingClientRect();

// Last: Apply change, get final position
element.classList.add("moved");
const last = element.getBoundingClientRect();

// Invert: Calculate delta, apply inverse transform
const deltaX = first.left - last.left;
const deltaY = first.top - last.top;
element.style.transform = `translate(${deltaX}px, ${deltaY}px)`;

// Play: Remove transform with transition
requestAnimationFrame(() => {
  element.style.transition = "transform 300ms ease-out";
  element.style.transform = "";
});

javascript
// First:获取元素初始位置
const first = element.getBoundingClientRect();

// Last:应用变化,获取最终位置
element.classList.add("moved");
const last = element.getBoundingClientRect();

// Invert:计算偏移量,应用反向变换
const deltaX = first.left - last.left;
const deltaY = first.top - last.top;
element.style.transform = `translate(${deltaX}px, ${deltaY}px)`;

// Play:移除变换并应用过渡效果
requestAnimationFrame(() => {
  element.style.transition = "transform 300ms ease-out";
  element.style.transform = "";
});

CSS Animation Techniques

CSS动画技巧

Keyframe Animation

关键帧动画

css
@keyframes fadeSlideIn {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.element {
  animation: fadeSlideIn 300ms ease-out forwards;
}

/* With steps */
@keyframes typewriter {
  from {
    width: 0;
  }
  to {
    width: 100%;
  }
}

.typing-text {
  animation: typewriter 2s steps(20) forwards;
}
css
@keyframes fadeSlideIn {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.element {
  animation: fadeSlideIn 300ms ease-out forwards;
}

/* 逐帧动画 */
@keyframes typewriter {
  from {
    width: 0;
  }
  to {
    width: 100%;
  }
}

.typing-text {
  animation: typewriter 2s steps(20) forwards;
}

Transition

过渡动画

css
.button {
  background: var(--primary);
  transform: scale(1);
  transition:
    background 150ms ease-out,
    transform 100ms ease-out;
}

.button:hover {
  background: var(--primary-hover);
  transform: scale(1.02);
}

.button:active {
  transform: scale(0.98);
  transition-duration: 50ms;
}
css
.button {
  background: var(--primary);
  transform: scale(1);
  transition:
    background 150ms ease-out,
    transform 100ms ease-out;
}

.button:hover {
  background: var(--primary-hover);
  transform: scale(1.02);
}

.button:active {
  transform: scale(0.98);
  transition-duration: 50ms;
}

Animation Shorthand

动画简写语法

css
/* animation: name duration timing-function delay
              iteration-count direction fill-mode play-state */

animation: slideIn 300ms ease-out 100ms 1 normal forwards running;

/* Common patterns */
animation: spin 1s linear infinite;
animation: pulse 2s ease-in-out infinite alternate;
animation: fadeIn 300ms ease-out forwards;

css
/* animation: 名称 时长 缓动函数 延迟
              迭代次数 方向 填充模式 播放状态 */

animation: slideIn 300ms ease-out 100ms 1 normal forwards running;

/* 常见模式 */
animation: spin 1s linear infinite;
animation: pulse 2s ease-in-out infinite alternate;
animation: fadeIn 300ms ease-out forwards;

JavaScript Animation Libraries

JavaScript动画库

Comparison

库对比

LibraryBest ForBundle Size
CSSSimple transitions0kb
Web Animations APINative, performant0kb
GSAPComplex, precise~60kb
Framer MotionReact ecosystem~50kb
anime.jsTimeline, SVG~17kb
Motion OneModern, lightweight~18kb
LottieAfter Effects export~50kb
库名称最佳适用场景包大小
CSS简单过渡效果0kb
Web Animations API原生高性能动画0kb
GSAP复杂高精度动画~60kb
Framer MotionReact生态系统~50kb
anime.js时间轴动画、SVG动画~17kb
Motion One现代轻量级动画~18kb
LottieAfter Effects导出动画~50kb

Framer Motion (React)

Framer Motion(React)

jsx
import { motion, AnimatePresence } from "framer-motion";

// Basic animation
<motion.div
  initial={{ opacity: 0, y: 20 }}
  animate={{ opacity: 1, y: 0 }}
  exit={{ opacity: 0, y: -20 }}
  transition={{ duration: 0.3, ease: "easeOut" }}
>
  Content
</motion.div>;

// Variants for complex animations
const containerVariants = {
  hidden: { opacity: 0 },
  visible: {
    opacity: 1,
    transition: {
      staggerChildren: 0.1,
    },
  },
};

const itemVariants = {
  hidden: { opacity: 0, y: 20 },
  visible: { opacity: 1, y: 0 },
};

<motion.ul variants={containerVariants} initial="hidden" animate="visible">
  {items.map((item) => (
    <motion.li key={item.id} variants={itemVariants}>
      {item.name}
    </motion.li>
  ))}
</motion.ul>;
jsx
import { motion, AnimatePresence } from "framer-motion";

// 基础动画
<motion.div
  initial={{ opacity: 0, y: 20 }}
  animate={{ opacity: 1, y: 0 }}
  exit={{ opacity: 0, y: -20 }}
  transition={{ duration: 0.3, ease: "easeOut" }}
>
  内容
</motion.div>;

// 复杂动画变体
const containerVariants = {
  hidden: { opacity: 0 },
  visible: {
    opacity: 1,
    transition: {
      staggerChildren: 0.1,
    },
  },
};

const itemVariants = {
  hidden: { opacity: 0, y: 20 },
  visible: { opacity: 1, y: 0 },
};

<motion.ul variants={containerVariants} initial="hidden" animate="visible">
  {items.map((item) => (
    <motion.li key={item.id} variants={itemVariants}>
      {item.name}
    </motion.li>
  ))}
</motion.ul>;

GSAP

GSAP

javascript
import { gsap } from "gsap";

// Basic tween
gsap.to(".element", {
  x: 100,
  opacity: 1,
  duration: 0.3,
  ease: "power2.out",
});

// Timeline
const tl = gsap.timeline();
tl.from(".header", { y: -100, duration: 0.5 })
  .from(".content", { opacity: 0, duration: 0.3 }, "-=0.2")
  .from(".button", { scale: 0.8, duration: 0.2 });

// ScrollTrigger
gsap.registerPlugin(ScrollTrigger);
gsap.to(".parallax", {
  y: -100,
  scrollTrigger: {
    trigger: ".section",
    start: "top center",
    end: "bottom center",
    scrub: true,
  },
});

javascript
import { gsap } from "gsap";

// 基础补间动画
gsap.to(".element", {
  x: 100,
  opacity: 1,
  duration: 0.3,
  ease: "power2.out",
});

// 时间轴动画
const tl = gsap.timeline();
tl.from(".header", { y: -100, duration: 0.5 })
  .from(".content", { opacity: 0, duration: 0.3 }, "-=0.2")
  .from(".button", { scale: 0.8, duration: 0.2 });

// 滚动触发动画
gsap.registerPlugin(ScrollTrigger);
gsap.to(".parallax", {
  y: -100,
  scrollTrigger: {
    trigger: ".section",
    start: "top center",
    end: "bottom center",
    scrub: true,
  },
});

Accessibility

无障碍设计

Respecting User Preferences

尊重用户偏好

css
/* Reduce motion for users who prefer it */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* Or provide simpler alternatives */
@media (prefers-reduced-motion: reduce) {
  .animated-element {
    /* Replace motion with opacity */
    animation: none;
    transition: opacity 200ms ease;
  }
}
css
/* 为偏好减少动画的用户优化 */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* 或提供更简单的替代方案 */
@media (prefers-reduced-motion: reduce) {
  .animated-element {
    /* 用透明度变化替代动效 */
    animation: none;
    transition: opacity 200ms ease;
  }
}

Safe Animation Practices

安全动画实践

AVOID for vestibular disorders:
✗ Parallax scrolling effects
✗ Zooming/scaling animations
✗ Spinning/rotating elements
✗ Auto-playing animations
✗ Flashing (>3 times/second)

SAFE alternatives:
✓ Opacity fades
✓ Color transitions
✓ Subtle position changes
✓ User-initiated animations
前庭障碍用户需避免:
✗ 视差滚动效果
✗ 缩放动画
✗ 旋转/自旋元素
✗ 自动播放动画
✗ 高频闪烁(>3次/秒)

安全替代方案:
✓ 透明度淡入淡出
✓ 颜色过渡
✓ 细微位置变化
✓ 用户触发的动画

WCAG Guidelines

WCAG指南

2.2.2 Pause, Stop, Hide:
- Auto-updating content can be paused
- No time limits on reading

2.3.1 Three Flashes:
- Nothing flashes more than 3x per second

2.3.3 Animation from Interactions:
- Motion can be disabled
- Triggered animations respect preferences

2.2.2 暂停、停止、隐藏:
- 自动更新的内容可暂停
- 阅读内容无时间限制

2.3.1 三次闪烁限制:
- 任何元素闪烁频率不超过3次/秒

2.3.3 交互触发动画:
- 动效可被禁用
- 触发的动画尊重用户偏好

Mobile Considerations

移动端适配

Touch Feedback

触摸反馈

css
/* iOS-style tap feedback */
.button {
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}

.button:active {
  opacity: 0.7;
  transition: opacity 50ms;
}

/* Ripple effect */
.ripple {
  position: relative;
  overflow: hidden;
}

.ripple::after {
  content: "";
  position: absolute;
  background: rgba(255, 255, 255, 0.3);
  border-radius: 50%;
  transform: scale(0);
  animation: ripple 400ms ease-out;
}
css
/* iOS风格点击反馈 */
.button {
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}

.button:active {
  opacity: 0.7;
  transition: opacity 50ms;
}

/* 波纹效果 */
.ripple {
  position: relative;
  overflow: hidden;
}

.ripple::after {
  content: "";
  position: absolute;
  background: rgba(255, 255, 255, 0.3);
  border-radius: 50%;
  transform: scale(0);
  animation: ripple 400ms ease-out;
}

Platform Conventions

平台设计规范

PlatformAnimation Style
iOSSpring physics, 300-500ms, subtle
AndroidMaterial motion, 200-300ms, emphasized
WebVaries, typically 200-400ms

平台动画风格
iOS弹簧物理效果,300-500ms,风格细腻
AndroidMaterial Design动效,200-300ms,强调交互
Web风格多样,通常200-400ms

Design System Integration

设计系统集成

Animation Tokens

动画令牌

css
:root {
  /* Durations */
  --duration-instant: 100ms;
  --duration-fast: 150ms;
  --duration-normal: 250ms;
  --duration-slow: 400ms;
  --duration-slower: 600ms;

  /* Easings */
  --ease-default: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-in: cubic-bezier(0.4, 0, 1, 1);
  --ease-out: cubic-bezier(0, 0, 0.2, 1);
  --ease-bounce: cubic-bezier(0.68, -0.55, 0.27, 1.55);

  /* Combined */
  --transition-default: var(--duration-normal) var(--ease-default);
  --transition-fast: var(--duration-fast) var(--ease-out);
}

/* Usage */
.element {
  transition: transform var(--transition-default);
}

css
:root {
  /* 时长令牌 */
  --duration-instant: 100ms;
  --duration-fast: 150ms;
  --duration-normal: 250ms;
  --duration-slow: 400ms;
  --duration-slower: 600ms;

  /* 缓动令牌 */
  --ease-default: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-in: cubic-bezier(0.4, 0, 1, 1);
  --ease-out: cubic-bezier(0, 0, 0.2, 1);
  --ease-bounce: cubic-bezier(0.68, -0.55, 0.27, 1.55);

  /* 组合令牌 */
  --transition-default: var(--duration-normal) var(--ease-default);
  --transition-fast: var(--duration-fast) var(--ease-out);
}

/* 使用示例 */
.element {
  transition: transform var(--transition-default);
}

Best Practices

最佳实践

DO:

建议遵循:

  • Animate with purpose (feedback, guidance)
  • Use GPU-accelerated properties
  • Keep durations under 500ms
  • Match animation to brand personality
  • Respect prefers-reduced-motion
  • Test on low-end devices
  • Use consistent timing system
  • 动画需具备明确目的(反馈、引导等)
  • 使用GPU加速属性
  • 动画时长控制在500ms以内
  • 动画风格匹配品牌调性
  • 尊重用户的减少动效偏好
  • 在低端设备上测试
  • 使用统一的时长系统

DON'T:

建议避免:

  • Animate for decoration alone
  • Block user interaction
  • Use excessive bounce/overshoot
  • Create motion sickness triggers
  • Forget exit animations
  • Ignore performance metrics
  • Delay essential content

  • 仅为装饰添加动画
  • 动画阻塞用户交互
  • 过度使用弹跳/回弹效果
  • 可能引发晕动症的动效
  • 忽略退出动画
  • 无视性能指标
  • 延迟核心内容加载

Animation Checklist

动画检查清单

Pre-Implementation

实现前:

  • Animation serves a purpose
  • Duration appropriate for action
  • Easing matches motion intent
  • Performance impact assessed
  • 动画具备明确的功能性目的
  • 时长与操作场景匹配
  • 缓动类型符合动效意图
  • 已评估性能影响

Implementation

实现中:

  • Uses GPU-accelerated properties
  • prefers-reduced-motion respected
  • Works on target devices
  • No layout thrashing
  • 使用GPU加速属性
  • 已适配prefers-reduced-motion
  • 在目标设备上可正常运行
  • 无布局抖动问题

Quality Check

质量检查:

  • Feels natural and responsive
  • Doesn't delay user
  • Consistent with design system
  • Accessible to all users
  • 动效自然且响应迅速
  • 不干扰用户操作
  • 与设计系统保持一致
  • 对所有用户无障碍