SVGアニメーションを書いてみよう
SVG と仲良くなろう
背景
普段 HTML/CSS で書けなさそうな図形は canvas(konvajs/node-canvas)に頼っているのですが、SVG について理解を深めたかったのと、canvas だとうまくアニメーション制御が書けず挫折したのでいい方法を模索するためです。
SVG とは
SVG とは「Scalable Vector Graphics(スケーラブル・ベクター・グラフィックス)」の略。
SVG は画像ファイルの一種で、画像や文字などをベクトルで描画するための指示を保存しており、拡大縮小でデータが劣化することがありません。
パスの記述方法
今回主に扱うのはpath
です。
path
では色々な直線や曲線を組み合わせて自由に書けますが、図形を書くために特化している書き方がいくつか用意されています。(rect
, circle
など)
コマンド
大文字の場合は絶対座標、小文字にすると現在の位置からの相対座標になります。
- M = 座標に移動する(move to)
- L = 指定された座標まで直線を引く(line to)
- H = 指定された座標まで水平線を引く(horizontal)
- V = 指定された座標まで垂線を引く(vertical)
- C = 曲線(curve to)
- S = 滑らかな曲線(smooth curve)
- Q = 2 次ベジェ曲線
- T = 滑らかな 2 次ベジェ曲線
- A = 楕円弧(Arc)
- Z = パスを閉じる
目指すゴール
SVG を使って 1 球速報の変化球の軌跡をアニメーションで描画できるようにする
(赤線は補助線)
path を書いてみる
<path
stroke="#984ea3"
fill="none"
strokeWidth="5"
d="M 299.5,50 s 84.53,122.72727272727272,-25.939999999999998,140"
/>
このコマンドは、
- 始点(299, 50)...絶対座標
- ベジェ制御点(84,122)...相対座標
- 終点(-25, 140) ...相対座標
のpathを書きます。
ベジェ曲線の書き方についてはこちらを参照。
SVG でアニメーション
CSSでアニメーションの定義を書きます。
svg path {
stroke-dasharray: 300px; /** 破線の間隔 */
stroke-dashoffset: 300px; /** 破線の開始位置 */
/** delayでアニメーションの開始を軌跡ごとにずらす */
animation: line_animation 3s both {delay}s;
}
/** 破線の開始位置をアニメーションでずらす */
@keyframes line_animation {
0% {
stroke-dashoffset: 300px;
}
100% {
stroke-dashoffset: 0px;
}
}
/** 球種表示のアニメーション */
@keyframes fade {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
ハマったところ
ベジェ曲線の書き方
制御点は通過点ではないので、軌道を動的に作るときに直感的に考えにくかった。
途中までしか描画されない!
SVG は描画領域が決まっているので、領域をはみ出てしまうと描画されない
例: M 10,10 L -10,10 (座標 10,10 に移動して、-10,10 まで線を引く)
x=0 のところで線が途切れてしまう。
考え方は canvas と同じ。
回転の中心点はどこだ
ストレート以外は三角形を描画して回転させているが、pathの領域が指定したサイズにならないのでtranslate
するにも中心点が指定できず、positionで調整するはめになった。
最適解が欲しいところ。
実装した例
参考
Discussion