VectorDrawableのpathDataを理解してアイコンからアイコンへのモーフアニメーションを自在に扱えるようになる

公開日: 2021年02月23日最終更新日: 2022年01月28日

VectorDrawableの中身を見るとpathDataを指定して図形を描画しているようですが、英字と数字が並んでいて、ぱっと見よくわからないので調べてみました。

VectorDrawableのXMLフォーマットはVectorDrawableに定義があります。 この中にpathDataのフォーマットはSVGのd attributeと同じと記載されています。以下の引用文です。

"android:pathData
Defines path data using exactly same format as "d" attribute in the SVG's path data. This is defined in the viewport space."

SVGの仕様書を確認すると、9.3.2. Specifying path data: the ‘d’ propertyに定義が書いてあります。
概要だけ書くと以下の通りです。

  • M / m は movetoコマンドでパスを開始する座標を指定する。(x y)の組を引数に取る。
  • Z / z は closepathコマンドで、サブパスを始点につなげて閉じる。
  • L / l は linetoコマンドで、現在位置から引数で与えられた座標まで線を引く
  • H / h は水平な線を引くコマンドで、V / vは垂直な線を引くコマンド。
  • 大文字は絶対座標指定、小文字は相対座標指定

ちなみに、vector drawableのpathDataを変化させてアニメーションする場合はコマンドの構造をアニメーション前後で合わせておく必要があります。 このときコマンドの順番で動きが変わるため、すべて時計回りに描画するなどルールを決めると良いです。

vector drawableを作る際には、Shapre Shifterという、SVGのアニメーションを作成するツールを使って確認すると便利です。

例として、AniumatedVectorDrawableを使用するで使用されているvector drawableを見てみます。
pathDataはM300,70 l 0,-70 70,70 0,0 -70,70zとなっており、コマンドごとに改行すると以下のようになります。

M300,70
l 0,-70
70,70
0,0
-70,70
z

同じコマンドの場合、引数を続けることでコマンドの文字を省略することができます。ここではlが省略されています。
順番にコマンドを見ていくと、次のようになっているのが読み取れます。

  • 描画開始位置を(300, 70)に移動
  • (300, 70)から相対座標(0, -70)の点(300, 0)に向かって線を引きながら移動する。
  • 現在位置(300, 0)から相対座標(70, 70)の点(370, 70)に向かって線を引きながら移動する。
  • 現在位置(370, 70)から相対座標(0, 0)の点(370, 70)に向かって線を引きながら移動する。ここではモーフアニメーション後のパスとコマンド構造を合わせるためにあえて同じ位置を指定しています。
  • 現在位置(370, 70)から相対座標(-70, 70)の点(300, 140)に向かって線を引きながら移動する。
  • zコマンドで、現在位置(300, 140)から部分パスの開始地点(300, 70)に線を引いてパスを閉じる。

ShapeShifterで見ると、これは以下のような画像になります。

vector

サンプルではrotationでこれを45度回転させているので角度が違いますが、画像がどのように指定されているかは分かりました。

コマンドと数字の構成になっているというのはなんとなく推測できましたが、こんな仕様になってたんですね。
理解できたので、これからはAndroidのVectorAssetをインポートして改造することができます。
好みの形にちょっと変えたり、アイコンからアイコンへのアニメーションも思いのままに作れそうです。

Animated Vector Drawableで押下時にアイコンの形が変わるアニメーションを作ってみましたではサンプルアプリを作って、モーフアニメーションによるアイコン切り替えを確認しています。