動画を作成する場合、専用のエディタが必要だと思われるでしょう。また、動画特有のビジュアル化されたUI/UXを使いこなす必要があるとも思うでしょう。しかし、Motion Canvasを使えば、TypeScriptでアニメーションを作成できます。プログラマー向けの動画作成ツールと言えそうです。
今回は、このMotion Canvasの使い方について解説します。
Motion Canvasとは
Motion Canvasは、TypeScriptでアニメーションを作成できるオープンソースのライブラリです。Reactのようなコンポーネントベースのアプローチを採用しており、コードでアニメーションを定義できます。これにより、プログラマーが馴染みやすい方法で動画やインタラクティブなコンテンツを作成できます。

描画はCanvasで行っており、描画している結果を画像として保存したり、FFMPEGを使ってMPEG4フォーマットの動画に出力できます。
動画の内容は編集できませんが、ブラウザ上でプレビューできるエディタが提供されています。
Motion Canvasのインストール
Motion Canvasを使う際には、以下のコマンドではじめるのが手軽です。
npm init @motion-canvas@latest
そして、作成したプロジェクトの中で npm install
を実行して依存関係をインストールします。
cd <プロジェクト名>
npm install
終わったら、以下のコマンドでエディタを起動します。
npm start
最初のアニメーションを作成
アニメーションの内容は、 src/scenes/example.tsx
に記述されています。
import {Circle, makeScene2D} from "@motion-canvas/2d";
import {createRef} from "@motion-canvas/core";
export default makeScene2D(function* (view) {
// Create your animations here
const circle = createRef<Circle>();
view.add(<Circle ref={circle} size={320} fill={"lightseagreen"} />);
yield* circle().scale(2, 2).to(1, 2);
});
この内容としては、円を描きつつ、拡大して元に戻すアニメーションを実行しています。

以下のコードは、円の位置を左右に動かしつつ、色を変化させるアニメーションです。 .position.x(300, 1).to(-300, 1)
の部分で、X座標を300から-300まで1秒かけて移動させています。また、 .fill('#e6a700', 1).to('#e13238', 1)
の部分で、色を #e6a700
から #e13238
に1秒かけて変化させています。
import {makeScene2D, Circle} from "@motion-canvas/2d";
import {all, createRef} from "@motion-canvas/core";
export default makeScene2D(function* (view) {
const myCircle = createRef<Circle>();
view.add(
<Circle
ref={myCircle}
// try changing these properties:
x={-300}
width={140}
height={140}
fill="#e13238"
/>,
);
yield* all(
myCircle().position.x(300, 1).to(-300, 1),
myCircle().fill("#e6a700", 1).to("#e13238", 1),
);
});

重ね合わせ
Motion Canvasでは、複数のシーンを重ねて表示できます。これは、TSX/JSXの構文を使って、コンポーネントをネストすることで実現します。以下のコードは、円と四角形、テキストを重ね合わせて表示するコード例です。
view.add(
<>
<Circle />
<Layout>
<Rect />
<Txt>Hi</Txt>
</Layout>
</>,
);
エフェクト
エフェクトは、状態の変化に応じて自動的に再評価される関数です。createEffect
関数を使って定義します。以下のコードは、信号(Signal)を使って円の数を動的に変更する例です。
import {Circle, Layout, makeScene2D} from "@motion-canvas/2d";
import {
createEffect,
createRef,
createSignal,
spawn,
waitFor,
} from "@motion-canvas/core";
export default makeScene2D(function* (view) {
const count = createSignal(0);
const container = createRef<Layout>();
view.add(<Layout alignItems={"center"} ref={container} layout />);
const circles: Circle[] = [];
createEffect(() => {
const targetCount = Math.round(count());
let i = circles.length;
// add any missing circles
for (; i < targetCount; i++) {
const circle = (<Circle fill={"white"} />) as Circle;
circles.push(circle);
container().add(circle);
spawn(circle.size(80, 0.3));
}
// remove any extra circles
for (; i > targetCount; i--) {
const circle = circles.pop()!;
spawn(circle.size(0, 0.3).do(() => circle.remove()));
}
});
count(1);
yield* waitFor(1);
count(6);
yield* waitFor(1);
count(4);
yield* count(0, 2);
yield* waitFor(1);
});

トゥイーン
トゥイーンは、ある状態から別の状態へスムーズに変化させるための手法です。Motion Canvasでは、 save
と restore
メソッドを使って、状態の保存と復元を行います。以下のコードは、円の位置とスケールを保存し、移動とスケール変更を行った後に、元の状態に戻す例です。
import {Circle, makeScene2D} from "@motion-canvas/2d";
import {all, createRef} from "@motion-canvas/core";
export default makeScene2D(function* (view) {
const circle = createRef<Circle>();
view.add(
<Circle
ref={circle}
size={150}
position={[-300, -300]}
fill={"#e13238"}
/>,
);
circle().save();
yield* all(circle().position.x(0, 1), circle().scale(1.5, 1));
circle().save();
yield* all(circle().position.y(0, 1), circle().scale(0.5, 1));
circle().save();
yield* all(circle().position.x(300, 1), circle().scale(1, 1));
yield* circle().restore(1);
yield* circle().restore(1);
yield* circle().restore(1);
});

カメラ
カメラを使ってシーン全体の表示を制御できます。カメラは、ズームやパンなどの操作が可能です。以下のコードは、カメラを使ってシーン全体をズームイン・ズームアウトする例です。
import {makeScene2D, Camera, Rect, Circle} from "@motion-canvas/2d";
import {createRef} from "@motion-canvas/core";
export default makeScene2D(function* (view) {
const camera = createRef<Camera>();
view.add(
<Camera ref={camera}>
<Rect size={100} fill={"lightseagreen"} position={[-100, -30]} />
<Circle size={80} fill={"hotpink"} position={[100, 30]} />
</Camera>,
);
yield* camera().zoom(2, 1);
yield* camera().zoom(0.5, 1.5);
yield* camera().zoom(1, 1);
});

プレゼンテーション
動画を再生するだけでなく、一旦停止もできます。それを使うと、プレゼンテーションのような操作が可能です。もちろん、各スライドではアニメーションが使えるので、ダイナミックなプレゼンテーションが実現できるでしょう。
import {makeScene2D, Txt} from "@motion-canvas/2d";
import {beginSlide, createRef, waitFor} from "@motion-canvas/core";
export default makeScene2D(function* (view) {
const title = createRef<Txt>();
view.add(<Txt ref={title} />);
title().text("FIRST SLIDE");
yield* beginSlide("first slide");
yield* waitFor(1); // try doing some actual animations here
title().text("SECOND SLIDE");
yield* beginSlide("second slide");
yield* waitFor(1);
title().text("LAST SLIDE");
yield* beginSlide("last slide");
yield* waitFor(1);
});

コンポーネント
あらかじめ用意されているコンポーネントを使うと、手軽に複雑なアニメーションが描けます。以下は Code
コンポーネントを使ってコードスニペットを表示する例です。
import {makeScene2D, Code} from '@motion-canvas/2d';
import {createRef} from '@motion-canvas/core';
export default makeScene2D(function* (view) {
const code = createRef<Code>();
view.add(
<Code
ref={code}
fontSize={28}
offsetX={-1}
x={-400}
code={`\
function example() {
const number = 9;
}`}
/>,
);
yield* code().code('const nine = 9;', 0.6).wait(0.6).back(0.6).wait(0.6);
});

他にもパスを描いたり、スプライン、Latexを使った数式表示などのコンポーネントがあります。
他の機能
Motion Canvasでは、音声ファイルや画像を取り込んだり、カスタムフォント、各種フィルター(ぼかしなど)などさまざまな機能が用意されています。
これらの機能を使えば、リッチなアニメーションや動画を作成できるでしょう。
まとめ
Motion Canvasは、TypeScriptでアニメーションや動画を作成できる強力なツールです。プログラマーにとって馴染みやすい方法で、複雑なアニメーションをコードで定義できます。サーバーと組み合わせれば、ユーザの入力に合わせた動的な動画生成も可能です。
サーバー側の仕組みは必要ですが、アプリの中でユーザーに動画を作ってもらうような機能も実現できるでしょう。ぜひ、Motion Canvasを試してみてください。
Motion Canvas - A TypeScript library for creating animated videos using the Canvas API.