SVG を transform で楽しくアニメーションするための最適化 〜僕らは幸せになるために生まれてきた〜

SVG を `transform` でアニメーションさせる場合、SVG 内の各要素を指定すると、原点が SVG 全体の左上なってしまいます。`translate` などは問題ないですが、`scale` や `rotate` などは思うようにアニメーションさせることができないです。

動かしたい要素をそれぞれ別の SVG に分けて、重ねて、原点を調整することで、対応することはできます。

しかし、それをひとつひとつ設定していくのは骨が折れる作業になります。とてもやってられないですね。だからといって、SVG ではない要素でつくってひとつひとつ配置していくのは涙が出るほど辛いでしょう。こんなことはエンジニアがやることでないです。僕たちは幸せになるために生まれてきたのだから。まだまだ理想にはほど遠いですが、とりあえず少しは楽になる方法を考えてみました。


# 作業手順
大きな作業手順としては以下の3ステップです。

1. svg を Adobe Illustrator で編集
2. SVG のサイズと位置情報を出力
3. スクリプト（Node）で最適化した要素を出力

では細かい手順をみていきましょう。

## 1. svg を Adobe Illustrator で編集

### 1-1. 最上位レイヤー直下でグループ化する
まずは、svg を Adobe Illustrator で開きます。
最上位レイヤーはひとつだけにして、動かしたい要素ごとに分けます。
グループ化されていないとデータを取得できないので、単体のパスであってもグループ化します。

```
レイヤー 1
  ├ <直線>
  ├ <長方形>
  └ <パス>
```
↓ グループ化

```
レイヤー 1
  ├ <グループ>
  ├ <グループ>
  └ <グループ>
```
※最上位レイヤー名はなんでもよいので初期値のままで `レイヤー 1` としています。

### 1-2. グループ名をつける
この名称が class 名や中心位置の設定などに反映されます。

#### class 名に関する命名ルール
名称は **英数字** と **`-`（ハイフン）**で、同じ名称は使えないです。
同じ名称ににしたい場合は **`_`（アンダースコア）**つなぎで番号を追加します。

##### 例）同じクラス名称のグループがひとつの場合

```
レイヤー 1
  ├ line
  ├ rect
  └ circle
```

##### 例）同じクラス名称のグループが複数の例

```
レイヤー 1
  ├ line_1
  ├ line_2
  └ line_3
```

#### 原点に関する命名ルール
上記の Class 名のあとに接尾詞として追加します。追加しない場合はグループの中心が原点になります。
**`*`（アスタリスク）**つなぎで原点を設定していきます。
グループからみた位置を ％ で X 軸 Y 軸の順番に **`,`（カンマ）**つなぎで指定します。
また、**`^` （キャレット）**からはじまる場合は SVG 要素の位置からみた指定になります。

##### 例）

```
レイヤー 1
  ├ line
  ├ rect*20,80
  └ circle*^50*50
```
**line** ： グループの中心（X 軸 Y 軸 ともに 50％）
**rect*20,80** ： グループの X 軸は 20％ で Y 軸は 80％
**circle*^50*50** ： SVG 要素の中心（X 軸 Y 軸 ともに 50％）

### 1-3. オプションを選択して保存する
保存時のオプションで `詳細オプション > CSS プロパティ > スタイル属性` を選択して保存します。
※これは SVG 要素を分割するため、スタイル属性をつかったほうが都合がよいからです。


## 2. グループのサイズと位置情報を txt で出力
Adobe Illustrator のプラグインである [Adobe-Export-Scripts](https://github.com/bronzehedwick/Adobe-Export-Scripts) をつかいます。

### 2-0. プラグインをつかう準備（初回のみ）
GitHub からダウンロードして、`Adobe-Export-Scripts-master > Illustrator > Export Layout.jsx` を以下の環境に応じたフォルダに設置する。

**Mac**: `~/Applications/Adobe Illustrator CC 2019/Presets/ja_JP/Scripts/`
**Windows**: `C:\Program Files\Adobe\Adobe Illustrator CC 2019\Presets\ja_JP\Scripts`
※環境によって変わります。主にバージョンと言語の箇所。

スクリプトを使えるようにするために、一度 Adobe Illustrator を再起動する必要があります。

### 2-1. スクリプトで txt を出力
`ファイル > スクリプト > Export Layout` からスクリプトを実行し txt を出力します。
※このときに png も出力されますが今回はつかいません。



## 3. SVG をアニメーションしやすく最適化
編集した svg と、出力した txt をつかって、アニメーションしやすく最適化した状態の要素をつくります。
これには僕が制作したスクリプトの [optimize-svg-transform](https://github.com/syuji-higa/optimize-svg-transform) をついかいます。

### 3-0. ダウンロードする（初回のみ）
GitHub からダウンロードして、任意の場所におきます。

### 3-1. ファイルの追加
`src` ディレクトリ直下に svg と txt を追加

### 3-2. スクリプトの実行
ターミナルで optimize-svg-transfrom をおいた場所に移動して、以下のコマンドを実行します。

```
$ node optimize-svg-transfrom.js -- [SVG の拡張子を除いたファイル名]
```

実行に成功すると、`dist` ディレクトリ直下に html が出力されます。
最適化されたざっくりな内容は以下です。

- グループごとの `svg` に分割
- グループごとに設定した `transform-origin` を設定
- 個々の `svg` を `div` でラップ
- 全体を `div` でラップ
- レスポンシブ対応


##### 例）

```
$ node optimize-svg-transfrom.js -- sample
```

```
┬ dist ─ sample.html
└ src ┬ sample.svg
      └ sample.txt
```


# サンプル
まあ、何をいっているか分かりづらいと思いますので、サンプルを用意しました。

## Illustrator で開いてグループ名を変更した SVG のキャプチャ
<img width="694" alt="" src="https://qiita-image-store.s3.amazonaws.com/0/25729/dce252fa-890d-d0df-2c07-b57198cda3cc.png">
かるく説明します。

- 四角は設定していないので自身を中心に動きます
- 円は全体を中心に動きます
- 三角は自身のひとつの頂点を中心に動きます（六芒星をかたどっているので、それぞれ別の頂点にしました）

## CSS スタイルをスタイル属性で保存した SVG
<p data-height="450" data-theme-id="0" data-slug-hash="EORwLN" data-default-tab="html,result" data-user="syuji-higa" data-pen-title="SVG Sample before Optimize" class="codepen">See the Pen <a href="https://codepen.io/syuji-higa/pen/EORwLN/">SVG Sample before Optimize</a> by Syuji Higa (<a href="https://codepen.io/syuji-higa">@syuji-higa</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
まあ、まんまですね。
Illustrator で保存したので、不要な要素や属性とかもありますが、スクリプトを通すと消えるので編集は不要です。

## スクリプトで最適化した SVG を適当にアニメーション
<p data-height="600" data-theme-id="0" data-slug-hash="bQKrPM" data-default-tab="result" data-user="syuji-higa" data-pen-title="Optimize SVG Sample" class="codepen">See the Pen <a href="https://codepen.io/syuji-higa/pen/bQKrPM/">Optimize SVG Sample</a> by Syuji Higa (<a href="https://codepen.io/syuji-higa">@syuji-higa</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

CSS の animation でサクッとアニメーションさせました。
まあ、こんな感じですよ。


# まとめ
どれだけの人がこの手法で幸せになるかは分からないですが、デザイナーがつくってフロントエンドエンジニアが動かすみたいな手順の場合は結構つかえるかと思います。
例えばインフォグラフィックスとかのアニメーションは大変だと思うんですけど、この手法なら少しは楽になりそうな気がしませんか？

まあ、はじめから After Effects とかでつくっちゃうのが一番はやそうですけどね。[Lottie](https://airbnb.design/lottie/) とかよいらしいので、次の案件でつかってみてボクはボクで勝手に幸せになろうかと思います。