Remotionでロゴアニメーションを作る — 実践ガイド
Remotionでロゴアニメーションを作る — 実践ガイド
ブランド動画においてロゴアニメーションは、視聴者が最初に目にし、最後に記憶に残る要素です。オープニングでブランドの世界観を印象づけ、インタビュー映像のロワーサード(字幕帯)では視聴中の存在感を維持し、エンドカードでは次の行動を促す錨として機能します。
Remotionはこうしたロゴアニメーションを、Reactコンポーネントとして一度書けば何度でも使い回せるかたちで実装できます。動画編集ソフトのタイムライン操作と根本的に異なるのは、データをpropsとして渡せる点です。会社名や色を変えるだけで、まったく違うブランドの動画ができあがります。本記事ではSVGの読み込みからパス描画・スケールフェード・スプリング回転・複数要素の段違いアニメーション・透過書き出しまで、実践的な手法を順番に解説します。
なぜロゴアニメーションはブランド動画に不可欠なのか
静止画のロゴがある動画と、ロゴが滑らかに現れる動画を比べたとき、多くの視聴者は後者を「クオリティが高い」と感じます。アニメーションは意図とコストを演出します。つまり、「この映像は手を抜いていない」というメッセージを無意識のうちに伝えるのです。
実用的な観点でも、アニメーションするロゴは機能します。長尺動画では定期的なロゴ出現が視聴者にブランドを繰り返し刷り込み、SNS動画では冒頭3秒でブランドを示すことが視聴完了率に影響するという知見もあります。
開発者にとってのメリットはさらに明確です。Remotionでロゴアニメーションコンポーネントを一本書けば、スタートアップの説明動画にも大企業の四半期報告書にも同じコンポーネントが使えます。色やタイミングをpropsで制御するだけで、同一のコードベースから無限のバリエーションを生み出せます。
SVGロゴをRemotionに取り込む
ロゴアニメーションにはSVG形式が最適です。ラスター画像(PNG・JPG)と違い、SVGファイルは内部のパス・グループ・図形をDOMノードとして公開しているため、JavaScriptとCSSから直接操作できます。この特性がパス描画アニメーションの基盤になります。
SVGをJSXに変換する
デザインツールが書き出したSVGファイルには、JSXで無効な属性(class、fill-opacity など)が含まれていることがあります。SVGRを使うと一括変換できます。
npx @svgr/cli --out-dir src/components -- src/assets/logo.svg
出力される .tsx ファイルは通常のReactコンポーネントとして扱えます。
手動インライン記述
小さなロゴであれば、SVGパスデータを直接コンポーネントに書き込む方法が最もシンプルです。
export const LogoMark: React.FC<{ color?: string }> = ({ color = "#1a1a2e" }) => (
<svg viewBox="0 0 120 80" xmlns="http://www.w3.org/2000/svg" style={{ width: "100%", height: "100%" }}>
<path
id="logo-path"
d="M10 40 C 20 10, 40 10, 50 40 C 60 70, 80 70, 90 40"
fill="none"
stroke={color}
strokeWidth="4"
strokeLinecap="round"
/>
<circle id="logo-dot" cx="100" cy="40" r="6" fill={color} />
</svg>
);
要素ごとに id を付与しておくと、後述の個別アニメーションで参照できます。
stroke-dashoffsetによるパス描画アニメーション
ロゴのラインが手書きのように画面に描き出される「パス描画」アニメーションは、ストロークで構成されたロゴに使えるもっとも印象的な手法です。仕組みはSVGの2つのプロパティに依存します。
stroke-dasharray— ダッシュ(線)の長さ。パス全長と同じ値を設定すると、ストローク全体が1本のダッシュになりますstroke-dashoffset— ダッシュのオフセット量。パス全長と同じ値を設定すると、ダッシュ全体がパスの外側に押し出されて見えなくなります
stroke-dashoffset をパス全長から0へアニメーションさせると、線が端から描かれていくように見えます。
パスの長さを測る
ブラウザでは path.getTotalLength() でSVGパスの全長を取得できます。Remotionのヘッドレスブラウザ環境でも同メソッドは使えますが、マウント前にアクセスできないため、ブラウザの開発者ツールコンソールで一度測定して定数として記述するのが実用的です。
import { interpolate, useCurrentFrame } from "remotion";
import { Easing } from "remotion";
const PATH_LENGTH = 247; // ブラウザで getTotalLength() を使って計測
const DRAW_DURATION = 45; // 30fpsで1.5秒
export const PathRevealLogo: React.FC = () => {
const frame = useCurrentFrame();
const dashOffset = interpolate(
frame,
[0, DRAW_DURATION],
[PATH_LENGTH, 0],
{
extrapolateRight: "clamp",
easing: Easing.bezier(0.4, 0, 0.2, 1),
}
);
return (
<svg viewBox="0 0 120 80" xmlns="http://www.w3.org/2000/svg">
<path
d="M10 40 C 20 10, 40 10, 50 40 C 60 70, 80 70, 90 40"
fill="none"
stroke="#1a1a2e"
strokeWidth="4"
strokeLinecap="round"
strokeDasharray={PATH_LENGTH}
strokeDashoffset={dashOffset}
/>
</svg>
);
};
複数パスを時差で描く
複数の線要素を持つロゴでは、各パスの開始フレームをずらすことで「次々と線が引かれていく」演出が生まれます。
const path1Offset = interpolate(frame, [0, 30], [P1_LEN, 0], { extrapolateRight: "clamp" });
const path2Offset = interpolate(frame, [10, 40], [P2_LEN, 0], { extrapolateRight: "clamp" });
const path3Offset = interpolate(frame, [20, 50], [P3_LEN, 0], { extrapolateRight: "clamp" });
スケールフェードで登場させる
スケールフェードはどんなロゴ形式(SVG・PNG・WebP)にも使える汎用手法です。ロゴが小さく透明な状態から、最終サイズへ拡大しながらフェードインします。シンプルながら「丁寧に作られた映像」という印象を与えます。
import { interpolate, spring, useCurrentFrame, useVideoConfig } from "remotion";
export const ScaleFadeLogo: React.FC<{ logoSrc: string }> = ({ logoSrc }) => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
const scale = spring({
fps,
frame,
config: {
damping: 14,
stiffness: 80,
mass: 0.8,
},
from: 0.6,
to: 1,
});
const opacity = interpolate(frame, [0, 12], [0, 1], {
extrapolateRight: "clamp",
});
return (
<div
style={{
transform: `scale(${scale})`,
opacity,
display: "flex",
alignItems: "center",
justifyContent: "center",
width: "100%",
height: "100%",
}}
>
<img src={logoSrc} style={{ width: 240, height: "auto" }} alt="logo" />
</div>
);
};
spring() は物理ベースのモーションを生成します。わずかなオーバーシュート(行き過ぎてから落ち着く動き)が加わり、機械的でなく有機的な動きになります。damping(高いほどバウンスが少ない)と stiffness(高いほど動きが速い)でブランドの個性に合わせて調整してください。
スプリング回転で躍動感を出す
回転とスケールを組み合わせると、スポーツ・ゲーム・エネルギー系ブランドに合うダイナミックな登場演出になります。回転角度は8〜15度に抑えるのがポイントです。それ以上回転するとカートゥーン的になってしまいます。
import { spring, useCurrentFrame, useVideoConfig } from "remotion";
export const RotateScaleLogo: React.FC<{ logoSrc: string }> = ({ logoSrc }) => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
const scale = spring({
fps,
frame,
config: { damping: 12, stiffness: 100, mass: 0.6 },
from: 0,
to: 1,
});
const rotate = spring({
fps,
frame,
config: { damping: 14, stiffness: 80, mass: 0.8 },
from: -12,
to: 0,
});
return (
<div
style={{
transform: `scale(${scale}) rotate(${rotate}deg)`,
display: "flex",
alignItems: "center",
justifyContent: "center",
width: "100%",
height: "100%",
}}
>
<img src={logoSrc} style={{ width: 200, height: "auto" }} alt="logo" />
</div>
);
};
2つの spring() が同一の frame を参照していることで、アニメーションが一貫したタイミングで収束します。別々のspringコンフィグを使っても、どちらかが不自然にまだ動き続けるという状態にはなりません。
Sequenceで複数要素を段違いに組み合わせる
実際のロゴは複数のパーツで構成されています。ロゴマーク(シンボル)・ワードマーク(会社名テキスト)・タグラインの3点セットが代表例です。それぞれが独立してアニメーションし、時間差で登場することで「丁寧に設計された演出」という印象が生まれます。
Remotionの <Sequence> コンポーネントは子コンポーネントのフレームカウンターをずらします。子コンポーネントは「自分が0フレームから始まっている」かのように動作するため、親の絶対フレームと独立してアニメーションロジックを書けます。
import { Sequence } from "remotion";
import { PathRevealLogo } from "./PathRevealLogo";
import { ScaleFadeLogo } from "./ScaleFadeLogo";
import { FadeInText } from "./FadeInText";
export const FullLogoBuild: React.FC<{
logoSrc: string;
companyName: string;
tagline?: string;
}> = ({ logoSrc, companyName, tagline }) => (
<div
style={{
position: "relative",
width: "100%",
height: "100%",
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
gap: 24,
background: "#ffffff",
}}
>
{/* ロゴマークを最初に描く */}
<Sequence from={0} durationInFrames={60}>
<PathRevealLogo />
</Sequence>
{/* ワードマークは20フレーム遅れてフェードイン */}
<Sequence from={20} durationInFrames={Infinity}>
<ScaleFadeLogo logoSrc={logoSrc} />
</Sequence>
{/* 社名テキストはさらに遅れて登場 */}
<Sequence from={35} durationInFrames={Infinity}>
<FadeInText text={companyName} />
</Sequence>
{/* タグラインは最後(省略可) */}
{tagline && (
<Sequence from={50} durationInFrames={Infinity}>
<FadeInText text={tagline} style={{ fontSize: 18, opacity: 0.6 }} />
</Sequence>
)}
</div>
);
durationInFrames={Infinity} を指定すると、その <Sequence> の子は親コンポジションが終わるまで表示され続けます。有限の数値を指定すると指定フレームで消えます。ロゴスティングでロゴが退場する必要がある場合はここで数値を指定します。
ロワーサード(字幕帯)でブランドを動かし続ける
インタビューやウェビナー録画など、話者が長時間映る映像では、ロワーサードにアニメーションするロゴを組み合わせることで、動画全体を通してブランドの存在感を維持できます。
import { interpolate, spring, useCurrentFrame, useVideoConfig } from "remotion";
interface LogoLowerThirdProps {
logoSrc: string;
name: string;
title: string;
exitFrame: number;
accentColor?: string;
}
export const LogoLowerThird: React.FC<LogoLowerThirdProps> = ({
logoSrc,
name,
title,
exitFrame,
accentColor = "#2563eb",
}) => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
// 下からスライドインで登場
const enterY = spring({
fps,
frame,
config: { damping: 16, stiffness: 90 },
from: 60,
to: 0,
});
// 退場は指定フレームから下にスライドアウト
const exitY = interpolate(frame, [exitFrame, exitFrame + 15], [0, 80], {
extrapolateLeft: "clamp",
extrapolateRight: "clamp",
});
return (
<div
style={{
position: "absolute",
bottom: 80,
left: 60,
transform: `translateY(${enterY + exitY}px)`,
display: "flex",
alignItems: "center",
gap: 12,
background: "rgba(255,255,255,0.96)",
borderLeft: `4px solid ${accentColor}`,
borderRadius: 4,
padding: "10px 20px",
boxShadow: "0 4px 24px rgba(0,0,0,0.12)",
}}
>
<img src={logoSrc} style={{ width: 32, height: 32, objectFit: "contain" }} alt="logo" />
<div>
<div style={{ fontSize: 18, fontWeight: 700, color: "#111", lineHeight: 1.2 }}>
{name}
</div>
<div style={{ fontSize: 14, color: accentColor, lineHeight: 1.4 }}>
{title}
</div>
</div>
</div>
);
};
exitFrame propで退場フレームをコントロールできるため、コンポジション全体の尺とは独立して、任意のタイミングでロワーサードを消すことができます。
動画イントロ(スティング)の構成
スティングは動画の冒頭に置く2〜5秒程度の短いブランドアニメーションです。ロゴが現れ、一定時間保持し、本編へ遷移します。
import { AbsoluteFill, Sequence, interpolate, useCurrentFrame, useVideoConfig } from "remotion";
export const LogoIntro: React.FC<{
logoSrc: string;
backgroundColor?: string;
}> = ({ logoSrc, backgroundColor = "#0f172a" }) => {
const frame = useCurrentFrame();
const { durationInFrames } = useVideoConfig();
const holdUntil = durationInFrames - 20;
const opacity = interpolate(
frame,
[holdUntil, durationInFrames],
[1, 0],
{ extrapolateLeft: "clamp", extrapolateRight: "clamp" }
);
return (
<AbsoluteFill
style={{
background: backgroundColor,
opacity,
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
<Sequence from={0}>
<ScaleFadeLogo logoSrc={logoSrc} />
</Sequence>
</AbsoluteFill>
);
};
ルートファイルへの登録例。
<Composition
id="LogoIntro"
component={LogoIntro}
durationInFrames={90} // 30fpsで3秒
fps={30}
width={1920}
height={1080}
defaultProps={{ logoSrc: "/logo.svg", backgroundColor: "#0f172a" }}
/>
透過背景で書き出す
放送・コンポジットワークフローでは、アルファチャンネル付きのロゴアニメーションをNLEタイムラインに重ねます。編集者はRemotionプロジェクトにアクセスする必要がなく、渡されたファイルをそのまま使えます。
PNGシーケンス(最も確実な方法)
npx remotion render src/index.ts LogoIntro \
--sequence \
--image-format=png \
--output=./output/logo-frames/
--sequence フラグを付けるとフレームごとにPNG画像が書き出されます。PNGはアルファチャンネルをネイティブサポートしています。Premiere Pro・DaVinci Resolve・Final Cut Proいずれもイメージシーケンスをタイムラインにインポートできます。
ProRes 4444
単一ファイルが必要な場合はProRes 4444でアルファチャンネルを保持できます。
npx remotion render src/index.ts LogoIntro \
--codec=prores \
--prores-profile=4444 \
--output=./output/logo-intro.mov
コンポジション側の設定
透過出力には、コンポジションの背景塗りを省略するか、AbsoluteFill に background: "transparent" を指定します。Reactコンポーネントでopacityがゼロのピクセルは、PNG・ProResともに透過領域として書き出されます。
プロの動画でよく見るロゴアニメーションパターン
多くのブランド動画を分析すると、いくつかのパターンが繰り返し登場します。
描画して定着 — パス描画や縮小スケールで現れ、わずかにオーバーシュートして落ち着く。動きながらも安定感があり、ブランドの自信を表現します。もっとも汎用性が高いパターンです。
左右から集まる — ワードマークを2分割し、左右からスライドして中央で合わさる。左右対称なロゴや、横組みの文字ロゴに特に効果的です。
マスクワイプ — 水平または垂直のマスクがスライドしてロゴを徐々に露出する。CSSの clip-path で実装でき、洗練された印象を与えます。
パーティクルアセンブル — ロゴのパーツが異なる方向から飛んできて組み立たる。技術的に複雑ですが、プロダクトローンチや企業紹介映像では強い印象を残します。
クロマティック登場 — モノクロやブランドカラーの単色で現れ、フルカラーへ移行する。色鮮やかなブランドアイデンティティを持つ企業に特に有効なドラマチックな演出です。
大半のプロジェクトでは、適切なスピードで実行された「描画して定着」パターンが最も効果的です。凝った演出より、フレームレートと物理パラメータの丁寧な調整に時間をかけることを優先してください。
FAQ
Q: PNGのロゴ画像でもこれらのアニメーションは使えますか? スケールフェードやスプリング回転など、CSSトランスフォームを使う手法はPNG画像でも問題なく使えます。パス描画アニメーションだけはSVGのパスデータが必要です。クライアントがPNGしか持っていない場合は、元のSVGマスターファイルを確認してください。プロが作成したロゴパッケージにはほぼ必ずSVG版が含まれています。
Q: 4K解像度でもロゴをシャープに表示するには? SVG形式を使ってください。SVGはベクターデータのため、どんな解像度でもシャープに表示されます。ラスター画像を使う場合は出力解像度以上のサイズが必要です。4K(3840×2160)出力に600pxのロゴを使うとぼやけます。
Q: SVGロゴのfill(塗り)カラーをアニメーションさせることはできますか?
できます。fill や stroke をpropsとして受け取り、interpolate でフレームに応じて値を変化させます。グレースケールからフルカラーへ移行する登場演出や、2色のブランドカラー間を遷移させる表現が可能です。
Q: spring()とinterpolate()をロゴアニメーションでどう使い分けるべきですか?
spring() は物理ベースのモーションを生成し、オーバーシュートと定着が自動的に加わります。バウンスや有機的な動きに適しています。interpolate() は指定した値の間を正確に補間します。「ちょうどフレーム30で変化が完了しなければならない」という精密な制御が必要な場面ではイージング付きの interpolate() を使います。
Q: ロゴアニメーションに効果音を付けることはできますか?
できます。Remotionの <Audio> コンポーネントを使います。効果音ファイルをインポートして、ロゴが画面に定着するフレームに合わせた <Sequence> の中に配置します。
import { Audio, Sequence } from "remotion";
<Sequence from={20}><Audio src={require("./logo-whoosh.mp3")} /></Sequence>
Q: 10個以上の要素を段違いに登場させる場合、Sequenceを10個書くのですか?
直接書く代わりに配列から動的に生成する方が保守しやすいです。要素の配列をマップして各要素に from={index * STAGGER_FRAMES} を割り当てます。
{elements.map((el, i) => (
<Sequence key={el.id} from={i * 8} durationInFrames={Infinity}>
<AnimatedElement data={el} />
</Sequence>
))}
Q: ロゴアニメーションだけを単体でレンダリングするには? ルートファイルにロゴアニメーション専用のコンポジションを登録し、その名前を指定してレンダリングします。
npx remotion render src/index.ts LogoAnimation --output=./logo.mp4
コンポジションは独立してレンダリング可能です。プロジェクト全体をレンダリングする必要はありません。
RenderCompのロゴアニメーションテンプレート
ロゴアニメーションコンポーネントをゼロから設計・実装すると、バリエーション(描画・スケールスプリング・段違い・ロワーサード・スティング)を揃えるまでに数日かかります。
RenderComp は本記事で解説したパターンをすべてカバーするプロダクション品質のRemotionロゴアニメーションテンプレートを提供しています。各テンプレートはTypeScriptのpropインターフェース付きで、透過PNGシーケンス書き出しにも対応済みです。プロジェクトに組み込んでロゴファイルを指定するだけで、初日からブロードキャスト品質のアニメーションを制作できます。
テンプレートの一覧は rendercomp.com でご確認ください。