元件重用與 Sequence
學會用 React 元件封裝動畫、用 Sequence 控制時序,讓影片專案更好維護。
為什麼要元件化?
當影片變得複雜,把所有邏輯塞在一個檔案裡會變得難以維護。好消息是——Remotion 的影片就是 React 元件,所以你可以用 React 的方式來組織程式碼。
封裝可重用的動畫元件
假設你要做一個片頭,裡面有標題和副標題。先把「淡入」這個行為封裝成元件:
import { useCurrentFrame, interpolate } from "remotion";
interface FadeInProps {
children: React.ReactNode;
delay?: number;
}
export const FadeIn: React.FC<FadeInProps> = ({ children, delay = 0 }) => {
const frame = useCurrentFrame();
const opacity = interpolate(frame - delay, [0, 20], [0, 1], {
extrapolateLeft: "clamp",
extrapolateRight: "clamp",
});
return <div style={{ opacity }}>{children}</div>;
};現在你可以在任何地方重複使用:
<FadeIn>第一段文字</FadeIn>
<FadeIn delay={15}>第二段文字</FadeIn>
<FadeIn delay={30}>第三段文字</FadeIn>用 Sequence 控制時序
<Sequence> 是 Remotion 的時序控制元件。它讓你指定「這段內容從第幾幀開始出現」:
import { AbsoluteFill, Sequence } from "remotion";
export const MyVideo: React.FC = () => {
return (
<AbsoluteFill style={{ backgroundColor: "#1a1a2e" }}>
<Sequence from={0} durationInFrames={60}>
<Title text="歡迎" />
</Sequence>
<Sequence from={30} durationInFrames={60}>
<Subtitle text="這是一個 Remotion 影片" />
</Sequence>
<Sequence from={60}>
<CallToAction text="立即開始" />
</Sequence>
</AbsoluteFill>
);
};重點:在 <Sequence> 內的元件,useCurrentFrame() 會從 0 開始計算。也就是說,Title 元件不需要知道自己是從整支影片的第幾幀開始——它只需要關心自己的動畫邏輯。這就是 Sequence 強大的地方。
用 Props 驅動配置
既然影片是 React 元件,你當然可以用 Props 來驅動:
interface IntroProps {
title: string;
subtitle: string;
accentColor: string;
}
export const Intro: React.FC<IntroProps> = ({
title,
subtitle,
accentColor,
}) => {
return (
<AbsoluteFill
style={{
justifyContent: "center",
alignItems: "center",
backgroundColor: "#0f0f1a",
}}
>
<Sequence from={0} durationInFrames={60}>
<FadeIn>
<h1 style={{ color: accentColor, fontSize: 72 }}>{title}</h1>
</FadeIn>
</Sequence>
<Sequence from={20} durationInFrames={60}>
<FadeIn>
<p style={{ color: "white", fontSize: 36 }}>{subtitle}</p>
</FadeIn>
</Sequence>
</AbsoluteFill>
);
};在 Composition 裡使用:
<Composition
id="Intro"
component={Intro}
durationInFrames={90}
fps={30}
width={1920}
height={1080}
defaultProps={{
title: "我的頻道",
subtitle: "每週更新",
accentColor: "#00d4ff",
}}
/>改一下 Props,就能產出不同版本的片頭——這就是程式化影片的威力。
完整範例:一個片頭動畫
結合以上所有概念,做一個完整的片頭:
import {
AbsoluteFill,
Sequence,
useCurrentFrame,
useVideoConfig,
spring,
interpolate,
} from "remotion";
const AnimatedText: React.FC<{ text: string; fontSize: number }> = ({
text,
fontSize,
}) => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
const progress = spring({ frame, fps, config: { damping: 12 } });
const translateY = interpolate(progress, [0, 1], [40, 0]);
const opacity = interpolate(progress, [0, 0.5], [0, 1], {
extrapolateRight: "clamp",
});
return (
<div
style={{
transform: `translateY(${translateY}px)`,
opacity,
fontSize,
color: "white",
fontWeight: "bold",
textAlign: "center",
}}
>
{text}
</div>
);
};
export const OpeningSequence: React.FC = () => {
return (
<AbsoluteFill
style={{
justifyContent: "center",
alignItems: "center",
backgroundColor: "#0f0f1a",
}}
>
<Sequence from={0} durationInFrames={60}>
<AnimatedText text="Remotion 社群" fontSize={80} />
</Sequence>
<Sequence from={20} durationInFrames={60}>
<AnimatedText text="用程式碼創作影片" fontSize={36} />
</Sequence>
<Sequence from={45} durationInFrames={45}>
<AnimatedText text="立即開始 →" fontSize={28} />
</Sequence>
</AbsoluteFill>
);
};小結
- 封裝元件 — 把動畫邏輯封裝成可重用的 React 元件。
- Sequence 控制時序 — 用
<Sequence>安排每段內容的出場時間,內部的useCurrentFrame()會自動歸零。 - Props 驅動 — 用 Props 讓同一個元件產出不同內容,實現批量化影片製作。
掌握這三個模式,你就能打造結構清晰、容易維護的 Remotion 影片專案。