(編注：SVGアニメーションを元記事にならい追加しました。リクエストありがとうございました。)

皆さんは線分のことをどう表現しますか？ 線分は、端点によって考えられるかもしれません。その端点をP0、P1と呼ぶことにしましょう。



線分を厳密に定義するならば、「P0とP1を結ぶ直線において、P0とP1の間にある全ての点の集合」と言えるかもしれません。これは以下のように表せるでしょう。



便利なことに、上記の定義から、その線分上のどこにある点の座標でも簡単に求めることができます。例えば、中点はL(0.5)にあります。

実は、2点間のどんな値でも、任意の精度で線形補間することが可能です。そのため、時間関数L(t)のtで線をたどるといった、より複雑なことができるのです。

P 0 P 1 L(0.5)

ここまで来ると、「それが曲線と何の関係があるのか？」と不思議に思うかもしれません。2つの点だけで正確に線分を描けるということは、かなり直感的に理解できそうです。では、以下の曲線を正確に描くにはどうすればよいでしょうか？

このような独特な曲線も、3つの点だけで描くことができるとわかります！

これは2次ベジェ曲線と呼ばれます。この複雑な帽子をかぶっているかのような曲線を得るための線分は1次ベジェ曲線と言えるかもしれません。その理由を見てみましょう。

まず、P0とP1を補間すると同時にP1とP2を補間するとどんな形になるか考えてみましょう。

P 0 P 1 P 2 B 0,1 ( 0.00 ) B 1,2 ( 0.00 )

それでは、B0,1(t)とB1,2(t)の線形補間を行ってみると…

P 0 P 1 P 2 B 0,1,2 ( 0.00 )

B0,1,2(t)の等式はB0,1とB1,2の等式にそっくりなことに注目してください。B0,1,2(t)のパスをたどるとどうなるか見てみましょう。

P 0 P 1 P 2

先ほどの曲線になりました！

高次のベジェ曲線

2本の1次ベジェ曲線を補間すると2次ベジェ曲線が得られるのと同様に、2本の2次ベジェ曲線を補間すると3次ベジェ曲線が得られます。

P 0 P 1 P 2 P 3

ここで、厄介な再帰的定義が含まれているのではないかと内心疑問が湧くかもしれません。実は、そのとおりなのです。

TypeScriptで（簡潔ですが効率の悪い形で）表すと、以下のようになるでしょう。

type Point = [number, number]; function B(P: Point[], t: number): Point { if (P.length === 1) return P[0]; const left: Point = B(P.slice(0, P.length - 1), t); const right: Point = B(P.slice(1, P.length), t); return [(1 - t) * left[0] + t * right[0], (1 - t) * left[1] + t * right[1]]; } // Evaluate a cubic spline at t=0.7 B([[0.0, 0.0], [0.0, 0.42], [0.58, 1.0], [1.0, 1.0]], 0.7)

ベクタ画像の3次ベジェ曲線

偶然にも3次ベジェ曲線は、単純さと正確さのバランスがうまく取れているので、様々な用途に役立つようです。Figmaのようなベクタ編集ツールで最もよく使われるタイプの曲線です。



Figmaでの3次ベジェ曲線

2つの塗り潰された丸●はP0とP3、2つのひし形◇はP1とP2だと考えてください。これらは、さらに複雑な曲線ベクタを構成する基本要素です。

フォントグリフは、TrueType（.ttf）フォントのベジェ曲線によって指定されます。



3次ベジェ曲線のvector networkとして表現された、Free Serif Italicの小文字の「e」

Scalable Vector Graphics（.svg）ファイルのフォーマットは、ベジェ曲線を2つの曲線プリミティブの1つとして使います。曲線プリミティブは、以下の画像の広範囲で使われています。



SVGフォーマットの3次スプラインの虎

アニメーションの3次ベジェ曲線

ベジェ曲線は、空間的曲線の表現に使われるのはもちろんですが、量間の曲線的関係の表現に使われても何ら不思議はありません。例えば、xとyの関係を示すのではなく、CSSのトランジションタイミング関数は時間の割合が出力値の割合と関連しています。

ベジェ曲線で定義されたトランジションタイミング関数

3次ベジェ曲線は、CSSでタイミング関数を表現する2つの方法のうちの1つです（もう1つはsteps()）。CSSのタイミング関数における cubic-bezier(x1, y1, x2, y2) の記法は、3次ベジェ曲線のP1とP2の座標を指定するものです。



transition-timing-function: cubic-bezier(x1, y1, x2, y2) のグラフ

Portion of CSS Property Value：CSSプロパティ値の割合

Portion of Time：時間の割合

オレンジ色のボールが動いているアニメーションを作成したいとしましょう。以下全てのグラフにおいて、赤色の線は一定速度での時間の動きを表しています。

linear (0.00, 0.00) (1.00, 1.00) ease (0.25, 0.10) (0.25, 1.00) ease-in (0.42, 0.00) (1.00, 1.00) ease-out (0.00, 0.00) (0.58, 1.00) ease-in-out (0.42, 0.00) (0.58, 1.00) (custom) (0.50, 1.00) (0.50, 0.00)

ベジェ曲線を使う理由

ベジェ曲線は、曲線を描くのに役立つ美しい抽象概念です。最もよく使われる形態である3次ベジェ曲線は、曲線を描いて格納するという問題を4つの座標を格納するという問題に変えます。

効率面での利点の他に、4つの制御点を曲線形の上に移すと直感的に理解しやすくなり、直接操作エディタに適したものとなります。

点の2つは曲線の端点となっているので、多くのベジェ曲線を使ってさらに複雑な構造を正確に作り上げることが容易になります。端点が正確に指定されることは、アニメーションの場合は常に大変便利です。イージング関数では、t=0%の時は初期値、t=100%の時は最終値なのです。

少し気づきにくい利点は、P0とP1を結ぶ線が、P0から出る曲線の接線になっているということです。このため、点対称の制御点を持つ2本の接続した曲線がある場合、接続点の傾きは両側で同じになることが保証されます。



左：点対称の制御点を持つ2本の接続した3次ベジェ曲線。

右：制御点が点対称でない場合。

ベジェ曲線のような数学的概念を扱う主な利点は、自分の問題領域の他の部分では全く認識できない問題に突き当たっても、何十年にもわたる数学研究を利用すれば大抵解決できるということです。

例えば、私は本記事を書くに当たって、上掲の曲線をアニメーション化するため、指定値tでベジェ曲線を分割する方法を学ばなければなりませんでした。ですが、それに関してうまく説明されている記事「A Primer on Bézier Curves: Splitting Curves」（ベジェ曲線入門：曲線を分割する）をすぐに見つけることができたのです。

参考資料と関連記事

また、Dudley Storeyの記事「Make SVG Responsive」（SVGをレスポンシブに）のおかげで、本記事で使ったインラインSVGの全てについて、モバイル環境でもうまく動作するようにできました。