motion

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Motion Animation Guidelines

Motion动画指南

You are an expert in Motion (motion.dev), JavaScript, TypeScript, and web animation performance. Follow these guidelines when creating animations.
您是Motion(motion.dev)、JavaScript、TypeScript和Web动画性能方面的专家。创建动画时请遵循以下指南。

Core Principles

核心原则

About Motion

关于Motion

  • Motion is the JavaScript animation library from the creator of Framer Motion
  • Use
    motion
    for vanilla JavaScript/TypeScript projects
  • Use
    motion/react
    for React projects (see framer-motion skill)
  • Designed for high performance with minimal bundle size
  • Motion是由Framer Motion开发者打造的JavaScript动画库
  • 在原生JavaScript/TypeScript项目中使用
    motion
  • 在React项目中使用
    motion/react
    (参考framer-motion相关内容)
  • 专为高性能设计,包体积极小

Installation

安装

bash
npm install motion
bash
npm install motion

Basic Import

基础导入

javascript
import { animate, scroll, inView, timeline } from "motion";
javascript
import { animate, scroll, inView, timeline } from "motion";

Basic Animations

基础动画

Simple Animation

简单动画

javascript
import { animate } from "motion";

// Animate a single element
animate(".element", { x: 100, opacity: 1 }, { duration: 0.5 });

// Animate with options
animate(
  ".element",
  { transform: "translateX(100px)" },
  {
    duration: 0.8,
    easing: "ease-out"
  }
);
javascript
import { animate } from "motion";

// 为单个元素添加动画
animate(".element", { x: 100, opacity: 1 }, { duration: 0.5 });

// 带配置项的动画
animate(
  ".element",
  { transform: "translateX(100px)" },
  {
    duration: 0.8,
    easing: "ease-out"
  }
);

Keyframes

关键帧动画

javascript
animate(
  ".element",
  {
    x: [0, 100, 50],      // Keyframe values
    opacity: [0, 1, 0.5]
  },
  { duration: 1 }
);
javascript
animate(
  ".element",
  {
    x: [0, 100, 50],      // 关键帧数值
    opacity: [0, 1, 0.5]
  },
  { duration: 1 }
);

Performance Optimization

性能优化

Animate Transform Properties

优先动画变换属性

javascript
// Best performance - GPU accelerated
animate(".element", {
  x: 100,           // translateX
  y: 50,            // translateY
  scale: 1.2,       // scale
  rotate: 45,       // rotate
  opacity: 0.5      // opacity
});

// Avoid when possible - triggers layout
animate(".element", {
  width: 200,       // Causes layout recalculation
  height: 150,      // Causes layout recalculation
  top: 50,          // Causes layout recalculation
  left: 100         // Causes layout recalculation
});
javascript
// 最佳性能 - GPU加速
animate(".element", {
  x: 100,           // translateX
  y: 50,            // translateY
  scale: 1.2,       // 缩放
  rotate: 45,       // 旋转
  opacity: 0.5      // 透明度
});

// 尽可能避免 - 会触发重排
animate(".element", {
  width: 200,       // 会导致布局重计算
  height: 150,      // 会导致布局重计算
  top: 50,          // 会导致布局重计算
  left: 100         // 会导致布局重计算
});

Use will-change

使用will-change

javascript
// Add will-change for transform animations
const element = document.querySelector(".element");
element.style.willChange = "transform";

animate(element, { x: 100 }, {
  onComplete: () => {
    element.style.willChange = "auto"; // Remove after animation
  }
});
javascript
// 为变换动画添加will-change
const element = document.querySelector(".element");
element.style.willChange = "transform";

animate(element, { x: 100 }, {
  onComplete: () => {
    element.style.willChange = "auto"; // 动画结束后移除
  }
});

Hardware Acceleration

硬件加速

Motion automatically uses hardware-accelerated properties when possible. For best performance:
  1. Prefer
    x
    ,
    y
    over
    left
    ,
    top
  2. Prefer
    scale
    over
    width
    ,
    height
  3. Use
    opacity
    for fade effects
  4. Use
    rotate
    over
    transform: rotate()
Motion会在可能的情况下自动使用硬件加速属性。为获得最佳性能:
  1. 优先使用
    x
    y
    而非
    left
    top
  2. 优先使用
    scale
    而非
    width
    height
  3. 使用
    opacity
    实现淡入淡出效果
  4. 使用
    rotate
    而非
    transform: rotate()

Timeline Animations

时间线动画

Create Timelines

创建时间线

javascript
import { timeline } from "motion";

const sequence = [
  [".header", { y: ["-100%", 0], opacity: [0, 1] }],
  [".content", { y: [50, 0], opacity: [0, 1] }, { at: "-0.3" }],
  [".footer", { y: [50, 0], opacity: [0, 1] }, { at: "-0.3" }]
];

const controls = timeline(sequence, {
  duration: 0.8,
  defaultOptions: { easing: "ease-out" }
});
javascript
import { timeline } from "motion";

const sequence = [
  [".header", { y: ["-100%", 0], opacity: [0, 1] }],
  [".content", { y: [50, 0], opacity: [0, 1] }, { at: "-0.3" }],
  [".footer", { y: [50, 0], opacity: [0, 1] }, { at: "-0.3" }]
];

const controls = timeline(sequence, {
  duration: 0.8,
  defaultOptions: { easing: "ease-out" }
});

Timeline Controls

时间线控制

javascript
const controls = timeline(sequence);

controls.play();
controls.pause();
controls.reverse();
controls.stop();
controls.finish();

// Seek to specific time
controls.currentTime = 0.5;
javascript
const controls = timeline(sequence);

controls.play();
controls.pause();
controls.reverse();
controls.stop();
controls.finish();

// 跳转到指定时间点
controls.currentTime = 0.5;

Scroll Animations

滚动动画

Basic Scroll Animation

基础滚动动画

javascript
import { scroll, animate } from "motion";

scroll(
  animate(".progress-bar", { scaleX: [0, 1] }),
  { target: document.querySelector("article") }
);
javascript
import { scroll, animate } from "motion";

scroll(
  animate(".progress-bar", { scaleX: [0, 1] }),
  { target: document.querySelector("article") }
);

Scroll-Linked Animation

滚动关联动画

javascript
scroll(({ y }) => {
  // y.progress is 0 to 1
  animate(".element", {
    opacity: y.progress,
    y: y.progress * 100
  }, { duration: 0 });
});
javascript
scroll(({ y }) => {
  // y.progress取值范围0到1
  animate(".element", {
    opacity: y.progress,
    y: y.progress * 100
  }, { duration: 0 });
});

Scroll with Container

容器内滚动动画

javascript
scroll(
  animate(".parallax", { y: [0, -100] }),
  {
    target: document.querySelector(".section"),
    offset: ["start end", "end start"]
  }
);
javascript
scroll(
  animate(".parallax", { y: [0, -100] }),
  {
    target: document.querySelector(".section"),
    offset: ["start end", "end start"]
  }
);

In-View Animations

视口触发动画

Trigger on Visibility

可见性触发

javascript
import { inView, animate } from "motion";

inView(".card", (info) => {
  animate(info.target, { opacity: 1, y: 0 }, { duration: 0.5 });

  // Return cleanup function
  return () => {
    animate(info.target, { opacity: 0, y: 20 }, { duration: 0.2 });
  };
});
javascript
import { inView, animate } from "motion";

inView(".card", (info) => {
  animate(info.target, { opacity: 1, y: 0 }, { duration: 0.5 });

  // 返回清理函数
  return () => {
    animate(info.target, { opacity: 0, y: 20 }, { duration: 0.2 });
  };
});

With Options

带配置项

javascript
inView(
  ".element",
  (info) => {
    animate(info.target, { scale: [0.8, 1], opacity: [0, 1] });
  },
  {
    margin: "-100px",  // Trigger 100px before entering viewport
    amount: 0.5        // Trigger when 50% visible
  }
);
javascript
inView(
  ".element",
  (info) => {
    animate(info.target, { scale: [0.8, 1], opacity: [0, 1] });
  },
  {
    margin: "-100px",  // 进入视口前100px触发
    amount: 0.5        // 元素50%可见时触发
  }
);

Stagger Animations

stagger动画(序列动画)

Stagger Multiple Elements

多元素 stagger 动画

javascript
import { stagger, animate } from "motion";

animate(
  ".list-item",
  { opacity: [0, 1], y: [20, 0] },
  { delay: stagger(0.1) }
);
javascript
import { stagger, animate } from "motion";

animate(
  ".list-item",
  { opacity: [0, 1], y: [20, 0] },
  { delay: stagger(0.1) }
);

Stagger from Center

从中心开始的 stagger 动画

javascript
animate(
  ".grid-item",
  { scale: [0, 1] },
  { delay: stagger(0.05, { from: "center" }) }
);
javascript
animate(
  ".grid-item",
  { scale: [0, 1] },
  { delay: stagger(0.05, { from: "center" }) }
);

Stagger with Easing

带缓动的 stagger 动画

javascript
animate(
  ".item",
  { x: ["-100%", 0] },
  {
    delay: stagger(0.1, {
      easing: "ease-out",
      start: 0.2
    })
  }
);
javascript
animate(
  ".item",
  { x: ["-100%", 0] },
  {
    delay: stagger(0.1, {
      easing: "ease-out",
      start: 0.2
    })
  }
);

Spring Animations

弹性动画

Use Springs for Natural Motion

使用弹性实现自然动效

javascript
animate(
  ".element",
  { scale: 1.2 },
  {
    easing: "spring",
    // or with custom spring settings
    easing: [0.34, 1.56, 0.64, 1] // Custom bezier curve
  }
);
javascript
animate(
  ".element",
  { scale: 1.2 },
  {
    easing: "spring",
    // 或自定义弹性设置
    easing: [0.34, 1.56, 0.64, 1] // 自定义贝塞尔曲线
  }
);

Spring Options

弹性配置项

javascript
animate(".element", { x: 100 }, {
  type: "spring",
  stiffness: 300,
  damping: 30
});
javascript
animate(".element", { x: 100 }, {
  type: "spring",
  stiffness: 300,
  damping: 30
});

Easing Functions

缓动函数

Built-in Easings

内置缓动

javascript
// Common easing values
animate(".element", { x: 100 }, { easing: "ease" });
animate(".element", { x: 100 }, { easing: "ease-in" });
animate(".element", { x: 100 }, { easing: "ease-out" });
animate(".element", { x: 100 }, { easing: "ease-in-out" });
animate(".element", { x: 100 }, { easing: "linear" });

// Cubic bezier
animate(".element", { x: 100 }, {
  easing: [0.25, 0.1, 0.25, 1]
});
javascript
// 常见缓动值
animate(".element", { x: 100 }, { easing: "ease" });
animate(".element", { x: 100 }, { easing: "ease-in" });
animate(".element", { x: 100 }, { easing: "ease-out" });
animate(".element", { x: 100 }, { easing: "ease-in-out" });
animate(".element", { x: 100 }, { easing: "linear" });

// 贝塞尔曲线
animate(".element", { x: 100 }, {
  easing: [0.25, 0.1, 0.25, 1]
});

Animation Controls

动画控制

Control Playback

播放控制

javascript
const controls = animate(".element", { x: 100 }, { duration: 1 });

// Control methods
controls.play();
controls.pause();
controls.stop();
controls.finish();
controls.reverse();

// Get/set time
controls.currentTime = 0.5;
console.log(controls.duration);

// Cancel animation
controls.cancel();
javascript
const controls = animate(".element", { x: 100 }, { duration: 1 });

// 控制方法
controls.play();
controls.pause();
controls.stop();
controls.finish();
controls.reverse();

// 获取/设置时间
controls.currentTime = 0.5;
console.log(controls.duration);

// 取消动画
controls.cancel();

Animation Events

动画事件

javascript
const controls = animate(
  ".element",
  { x: 100 },
  {
    duration: 1,
    onComplete: () => console.log("Done!")
  }
);

// Promise-based
controls.finished.then(() => {
  console.log("Animation finished");
});
javascript
const controls = animate(
  ".element",
  { x: 100 },
  {
    duration: 1,
    onComplete: () => console.log("完成!")
  }
);

// 基于Promise的方式
controls.finished.then(() => {
  console.log("动画已完成");
});

Accessibility

无障碍适配

Respect Reduced Motion

尊重减少动画偏好

javascript
const prefersReducedMotion = window.matchMedia(
  "(prefers-reduced-motion: reduce)"
).matches;

animate(
  ".element",
  { x: 100, opacity: 1 },
  {
    duration: prefersReducedMotion ? 0 : 0.5,
    easing: prefersReducedMotion ? "linear" : "ease-out"
  }
);
javascript
const prefersReducedMotion = window.matchMedia(
  "(prefers-reduced-motion: reduce)"
).matches;

animate(
  ".element",
  { x: 100, opacity: 1 },
  {
    duration: prefersReducedMotion ? 0 : 0.5,
    easing: prefersReducedMotion ? "linear" : "ease-out"
  }
);

Create Accessible Wrapper

创建无障碍封装函数

javascript
function safeAnimate(element, keyframes, options = {}) {
  const reducedMotion = window.matchMedia(
    "(prefers-reduced-motion: reduce)"
  ).matches;

  return animate(element, keyframes, {
    ...options,
    duration: reducedMotion ? 0 : (options.duration ?? 0.3)
  });
}
javascript
function safeAnimate(element, keyframes, options = {}) {
  const reducedMotion = window.matchMedia(
    "(prefers-reduced-motion: reduce)"
  ).matches;

  return animate(element, keyframes, {
    ...options,
    duration: reducedMotion ? 0 : (options.duration ?? 0.3)
  });
}

Integration with Frameworks

与框架集成

Vanilla JavaScript

原生JavaScript

javascript
document.addEventListener("DOMContentLoaded", () => {
  animate(".hero", { opacity: [0, 1], y: [30, 0] });
});
javascript
document.addEventListener("DOMContentLoaded", () => {
  animate(".hero", { opacity: [0, 1], y: [30, 0] });
});

With Event Listeners

结合事件监听器

javascript
const button = document.querySelector(".button");

button.addEventListener("mouseenter", () => {
  animate(button, { scale: 1.05 }, { duration: 0.2 });
});

button.addEventListener("mouseleave", () => {
  animate(button, { scale: 1 }, { duration: 0.2 });
});
javascript
const button = document.querySelector(".button");

button.addEventListener("mouseenter", () => {
  animate(button, { scale: 1.05 }, { duration: 0.2 });
});

button.addEventListener("mouseleave", () => {
  animate(button, { scale: 1 }, { duration: 0.2 });
});

Cleanup

清理工作

Cancel Animations

取消动画

javascript
const controls = animate(".element", { x: 100 });

// Later, cancel it
controls.cancel();
javascript
const controls = animate(".element", { x: 100 });

// 之后取消动画
controls.cancel();

Cleanup Pattern

清理模式

javascript
class AnimatedComponent {
  constructor(element) {
    this.element = element;
    this.animations = [];
  }

  animate(keyframes, options) {
    const controls = animate(this.element, keyframes, options);
    this.animations.push(controls);
    return controls;
  }

  destroy() {
    this.animations.forEach(anim => anim.cancel());
    this.animations = [];
  }
}
javascript
class AnimatedComponent {
  constructor(element) {
    this.element = element;
    this.animations = [];
  }

  animate(keyframes, options) {
    const controls = animate(this.element, keyframes, options);
    this.animations.push(controls);
    return controls;
  }

  destroy() {
    this.animations.forEach(anim => anim.cancel());
    this.animations = [];
  }
}

Best Practices Summary

最佳实践总结

  1. Use transform properties (x, y, scale, rotate) for best performance
  2. Add will-change before complex animations, remove after
  3. Use timeline for sequenced animations
  4. Use scroll() for scroll-linked effects
  5. Use inView() for viewport-triggered animations
  6. Use stagger() for animating multiple elements
  7. Prefer springs for interactive/gesture animations
  8. Always respect reduced motion preferences
  9. Cancel animations when no longer needed
  10. Test performance on actual devices
  1. 使用变换属性(x、y、scale、rotate)以获得最佳性能
  2. 复杂动画前添加will-change,动画结束后移除
  3. 使用时间线实现序列动画
  4. 使用scroll()实现滚动关联效果
  5. 使用inView()实现视口触发动画
  6. 使用stagger()实现多元素序列动画
  7. 交互/手势动画优先使用弹性效果
  8. 始终尊重减少动画的用户偏好
  9. 不再需要时及时取消动画
  10. 在真实设备上测试性能