VectorDrawable、AnimatedVectorDrawableってなんなの。SVGから変換できるけどそれとは何が違うのって思いました。
SVGとVectorDrawable
なので何が違うか確認しましょう。
適当に大きさの違う円形と楕円形のSVGを作ったものとそれをAnimatedVectorDrawableに変換したものです。
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg width="100%" height="100%" viewBox="0 0 48 48" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;"> <circle cx="8.922" cy="10.305" r="5.041" style="fill:rgb(255,48,22);"/> <g transform="matrix(1.84649,0,0,1.84649,-17.4162,-40.4344)"> <circle cx="29.086" cy="27.926" r="5.086" style="fill:rgb(255,48,22);"/> </g> <g transform="matrix(3.97807,0,0,1.84649,-91.5926,-18.1741)"> <circle cx="29.086" cy="27.926" r="5.086" style="fill:rgb(255,48,22);"/> </g> </svg>
circleが3つあるのでそれぞれ独立して定義されているのがわかります。
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"> <aapt:attr name="android:drawable"> <vector android:name="vector" android:width="48dp" android:height="48dp" android:viewportWidth="48" android:viewportHeight="48"> <path android:name="path_1" android:pathData="M 8.922 5.264 C 7.858 5.264 6.82 5.601 5.959 6.227 C 5.098 6.852 4.457 7.735 4.128 8.747 C 3.799 9.76 3.799 10.85 4.128 11.863 C 4.457 12.875 5.098 13.758 5.959 14.383 C 6.82 15.009 7.858 15.346 8.922 15.346 C 10.258 15.346 11.542 14.815 12.487 13.87 C 13.432 12.925 13.963 11.641 13.963 10.305 C 13.963 8.969 13.432 7.685 12.487 6.74 C 11.542 5.795 10.258 5.264 8.922 5.264 Z M 36.291 1.739 C 33.801 1.739 31.411 2.73 29.65 4.49 C 27.89 6.251 26.9 8.641 26.9 11.131 C 26.9 13.62 27.89 16.011 29.65 17.771 C 31.411 19.532 33.801 20.522 36.291 20.522 C 38.781 20.522 41.171 19.532 42.931 17.771 C 44.692 16.011 45.682 13.62 45.682 11.131 C 45.682 8.641 44.692 6.251 42.931 4.49 C 41.171 2.73 38.781 1.739 36.291 1.739 Z M 24.114 24 C 18.75 24 13.6 24.99 9.807 26.75 C 6.014 28.511 3.881 30.901 3.881 33.391 C 3.881 35.881 6.014 38.271 9.807 40.032 C 13.6 41.792 18.75 42.782 24.114 42.782 C 28.386 42.782 32.55 42.154 36.006 40.989 C 39.462 39.823 42.036 38.179 43.356 36.293 C 44.676 34.407 44.676 32.375 43.356 30.489 C 42.036 28.603 39.462 26.959 36.006 25.793 C 32.55 24.628 28.386 24 24.114 24 Z" android:fillColor="#ff3016" android:strokeWidth="1"/> </vector> </aapt:attr> </animated-vector>
こちらはデータ量を見るにpathDataが本体みたいですが一個になってしまっています。
正方形でも長方形でもMから始まってZで終わります。唯一違うのは間のアルファベットです。
VectorDrawableとは
じゃあこのpathDataはどのようなフォーマットなのでしょうか。
ドキュメントを見る前に少し推測してみます。端いっぱいの円形です。
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"> <aapt:attr name="android:drawable"> <vector android:name="vector" android:width="10dp" android:height="10dp" android:viewportWidth="10" android:viewportHeight="10"> <path android:name="path" android:pathData="M 5 0 C 3.944 -0.001 2.914 0.333 2.06 0.954 C 1.205 1.574 0.568 2.45 0.242 3.455 C -0.085 4.459 -0.085 5.542 0.242 6.546 C 0.568 7.551 1.205 8.426 2.06 9.047 C 2.914 9.668 3.944 10.002 5 10.001 C 6.057 10.002 7.087 9.668 7.941 9.047 C 8.796 8.426 9.433 7.551 9.759 6.546 C 10.086 5.542 10.086 4.459 9.759 3.455 C 9.433 2.45 8.796 1.574 7.941 0.954 C 7.087 0.333 6.057 -0.001 5 0 Z" android:fillColor="#ff3016" android:strokeWidth="1"/> </vector> </aapt:attr> </animated-vector>
- M 5 0
widthとheightが10で円形で「5,0」始点ですね。 アルファベット+数値のセットみたいですね - C 3.944 -0.001 2.914 0.333 2.06 0.954
よくわかりません。
要素を表すアルファベット1文字+そのアルファベットに対応した値の個数みたいですね。
次に正方形のデータです。
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"> <aapt:attr name="android:drawable"> <vector android:name="vector" android:width="10dp" android:height="10dp" android:viewportWidth="10" android:viewportHeight="10"> <path android:name="path_1" android:pathData="M -0.002 0 L 9.999 0 L 9.999 10 L -0.002 10 Z" android:fillColor="#ff3016" android:strokeWidth="1"/> </vector> </aapt:attr> </animated-vector>
- M -0.002 0 L 9.999 0 L 9.999 10 L -0.002 10 Z
若干ぶれてるみたいなので見やすいように手動で補正します。↓ - M 0 0 L 10 0 L 10 10 L 0 10 Z
点と点を繋いでいくように描画するみたいですね。
流石にもう分からないのでドキュメントを読みます。
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.
https://developer.android.com/reference/android/support/graphics/drawable/VectorDrawableCompat
svgの "d" attribute と一緒と書いてあります。
D Property
The \
value specifies a shape using a path data string. The contents of the \ value must match the svg-path EBNF grammar defined below, and errors within the string are handled according to the rules in the Path Data Error Handling section. If the path data string contains no valid commands, then the behavior is the same as the none value.
https://svgwg.org/svg2-draft/paths.html#DProperty
EBNFの文法がリンクされています。
https://svgwg.org/svg2-draft/paths.html#PathDataBNF
エラーハンドリングの方法も書かれています。
https://svgwg.org/svg2-draft/paths.html#PathDataErrorHandling
アニメーション
アニメーションの事も記述されています。
The \
value specifies a shape using a path data string. The contents of the \ value must match the svg-path EBNF grammar defined below, and errors within the string are handled according to the rules in the Path Data Error Handling section. If the path data string contains no valid commands, then the behavior is the same as the none value.
2つのパスの構造が一緒じゃないとスムーズにアニメーションできない。一緒じゃないなら離散アニメーションで補完しろ。的なことが書いてあります。
離散アニメーション
https://drafts.csswg.org/web-animations/#discrete-animation-type-section
コマンド一覧
大文字は絶対座標で小文字は相対座標です。
- 絶対移動(M m)
- 終了(Z z)
最初の点に接続して終了します - 線(L l H h V v)
- 三次元ベジエ(C c S s)
- 二次元ベジエ(Q q T t)
- 楕円形コマンド(A a)
おわる
これ以上はSVGの説明になるので省きますが大体の雰囲気は掴めたと思います。
なんでCircleがCの三次元ベジエで表されていたのかはこれはおそらくアニメーションがしやすいようにでしょうね。円から直線に変わる時にスムーズにアニメーションするには構造が同じでないといけないので。