如何用JavaScript实现动画_有哪些关键步骤

动画本质是定时修改CSS属性,需用requestAnimationFrame实现60fps同步,配合transform/opacity避免重排,结合缓动函数提升质感,并注意及时终止与帧率适配。

动画的本质是定时修改样式

JavaScript 动画不是“播放一个视频”,而是通过高频(通常每秒 60 次)反复更新元素的 CSS 属性(比如 transformopacity),利用人眼视觉暂留形成连续运动效果。关键不在于“动”,而在于“怎么动得顺、不卡、可控制”。

requestAnimationFrame 是现代动画的起点

别用 setTimeoutsetInterval 做动画——它们不和屏幕刷新同步,容易掉帧、抖动、耗电。必须用 requestAnimationFrame,它会把回调安排在浏览器下一次重绘前执行,天然契合 60fps 节奏。

实操要点:

  • 每次执行完动画逻辑后,**必须主动再调一次** requestAnimationFrame,否则只执行一帧
  • 传入的回调函数会收到一个时间戳参数(DOMHighResTimeStamp),可用于计算真实经过时间,避免因帧率波动导致速度不一致
  • cancelAnimationFrame 主动终止,尤其在组件卸载或用户交互中断时,否则可能引发内存泄漏
let animationId;
function animate(timestamp) {
  // 计算 delta 时间(毫秒),用于匀速/缓动逻辑
  if (!lastTime) lastTime = timestamp;
  const delta = timestamp - lastTime;
  lastTime = timestamp;

// 更新元素位置:例如 translateX += speed * (delta / 16) element.style.transform = translateX(${x}px);

// 继续下一帧 animationId = requestAnimationFrame(animate); } animationId = requestAnimationFrame(animate);

transformopacity 避免重排(reflow)

直接改 lefttopwidth 等会触发浏览器重新计算布局(reflow),开销大、易卡顿。应优先使用仅触发重绘(repaint)甚至合成(composite)的属性:

  • transform: translateX()translateY()scale()rotate()
  • opacity
  • 确保目标元素有独立的合成层(可通过 will-change: transformtransform: translateZ(0) 触发,但别滥用)

错误示例:element.style.left = x + 'px' —— 强制重排,动画一卡就明显。

缓动函数决定动画的“质感”

线性运动(linear)生硬,真实感强的动画需要缓动(easing)。自己写简单缓动如 easeOutQuad 很容易,没必要总引入库:

function easeOutQuad(t) {
  // t ∈ [0, 1],返回 [0, 1] 的插值比例
  return t * (2 - t);
}

// 使用示例:从 0 到 100px,持续 500ms const start = 0; const end = 100; const duration = 500; let startTime = null;

function step(timestamp) { if (!startTime) startTime = timestamp; const elapsed = timestamp - startTime; const progress = Math.min(elapsed / duration, 1); const eased = easeOutQuad(progress); const current = start + (end

- start) * eased;

element.style.transform = translateX(${current}px);

if (progress < 1) requestAnimationFrame(step); }

注意:缓动函数输入必须归一化到 [0, 1],输出也应是 [0, 1],再映射到实际数值范围——这点漏掉会导致动画错位或超限。

真正难的不是让东西动起来,而是让动的过程响应及时、中止干净、适配不同设备帧率,以及在 DOM 大量更新时不让动画被挤掉帧。这些细节不处理,用户第一感觉就是“卡”或“不跟手”。