Remotion LabRemotion Lab
入門動畫入門

動畫入門

學會 useCurrentFrame、interpolate 和 spring 三大動畫技巧,打造流暢的 Remotion 動畫。

為什麼不能用 CSS Animation?

你可能會想:「我直接用 CSS animationtransition 不就好了?」

答案是不行。原因在於 Remotion 的渲染方式——它是逐幀渲染的。Remotion 不是在瀏覽器裡播放動畫,而是一幀一幀地截圖,再組合成影片。CSS 動畫依賴瀏覽器的時間系統,但 Remotion 需要的是:「在第 N 幀,這個元素應該長什麼樣?」

所以,所有動畫都必須是 frame 的函數

基礎:useCurrentFrame()

useCurrentFrame() 是一切的起點。它回傳目前的幀數,你用這個數字來計算任何視覺屬性:

import { useCurrentFrame } from "remotion";
 
export const FadeIn: React.FC = () => {
  const frame = useCurrentFrame();
  const opacity = Math.min(1, frame / 30);
 
  return (
    <div style={{ opacity, fontSize: 60, color: "white" }}>
      淡入效果
    </div>
  );
};

前 30 幀內,opacity 從 0 線性增加到 1。

進階:interpolate()

手動算數學很快就會變得複雜。interpolate() 幫你做值的映射:

import { useCurrentFrame, interpolate } from "remotion";
 
export const SlideIn: React.FC = () => {
  const frame = useCurrentFrame();
 
  const translateX = interpolate(frame, [0, 30], [200, 0], {
    extrapolateRight: "clamp",
  });
 
  const opacity = interpolate(frame, [0, 20], [0, 1], {
    extrapolateRight: "clamp",
  });
 
  return (
    <div
      style={{
        transform: `translateX(${translateX}px)`,
        opacity,
        fontSize: 48,
        color: "white",
      }}
    >
      從右側滑入
    </div>
  );
};

interpolate(frame, [0, 30], [200, 0]) 的意思是:「當 frame 從 0 到 30 時,把值從 200 映射到 0。」extrapolateRight: "clamp" 確保超過 30 幀後值不會繼續變化。

彈跳效果:spring()

interpolate() 產生的是線性動畫,看起來有點機械。spring() 模擬彈簧物理,讓動畫更自然:

import { useCurrentFrame, useVideoConfig, spring } from "remotion";
 
export const BounceIn: React.FC = () => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();
 
  const scale = spring({
    frame,
    fps,
    config: { damping: 8, stiffness: 200 },
  });
 
  return (
    <div
      style={{
        transform: `scale(${scale})`,
        fontSize: 60,
        color: "white",
      }}
    >
      彈跳!
    </div>
  );
};

spring 的參數

參數預設值效果
damping10越高 = 越少彈跳
stiffness100越高 = 動畫越快
mass1越高 = 越慢、越有慣性

實戰:組合多種效果

把以上技巧結合,做一個帶有滑動 + 彈跳 + 淡入的標題動畫:

import {
  useCurrentFrame,
  useVideoConfig,
  spring,
  interpolate,
} from "remotion";
 
export const AnimatedTitle: React.FC = () => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();
 
  const progress = spring({
    frame,
    fps,
    config: { damping: 12 },
  });
 
  const translateY = interpolate(progress, [0, 1], [50, 0]);
  const opacity = interpolate(progress, [0, 0.5], [0, 1], {
    extrapolateRight: "clamp",
  });
 
  return (
    <div
      style={{
        transform: `translateY(${translateY}px)`,
        opacity,
        fontSize: 72,
        color: "white",
        fontWeight: "bold",
      }}
    >
      組合動畫效果
    </div>
  );
};

這裡的技巧是:先用 spring() 產生一個 0→1 的進度值,再用 interpolate() 把這個進度值映射到不同的視覺屬性。這樣所有屬性會跟著同一個彈簧曲線同步變化。

下一步

學會了基本動畫技巧後,接下來可以學習如何用 Sequence 組織影片結構,打造更複雜的影片專案。