SVGアイコンを自作してみたい、イラレとかのペイントツールなしで

svgアイコンの中身に対しての解説があまりない気がしたので書いてみる
svgという概念に関しての解説とかはあるけど、（Illustratorでかけるよーとか）FontAwesomeとかFetherみたいなアイコンを自分で作ってみたいなーとか思ってもなかなか日本語だと情報がない（少なくとも私のような雑魚向けには）
イラレとかInkScapeの使い方とかはよくわからんしインストールとかもなんかめんどくさそうだったので、できればコードとウェブツールだけでぱぱっと試してみたい

で、数か月前の私は英語力（と英語での最低限の検索力）が今以上に壊滅的だったので目的の情報に辿り着くことができなかったのだけど、最近になって`how to draw svg icon`とかで検索してみるといい感じの情報が出てくるっぽいことに気づいたので自分が気になっていたことをぱっとまとめてみる（以前はたぶん`how to create~`とかで検索して、検索結果の上のほうのやつを見て力尽きたんだと思う。今思えばcreateの方が曖昧でしたね）

ほとんど英語の情報しかないのだからそれを漁るしかないわけだけど、英語は気合と雰囲気とGoogle翻訳[^1]があればなんとかなると思ってるのでがんばる。コードに関してはGoogle翻訳が利かなくてつらいのでがんばるしかない（前はコードわからん・英語の補足情報も読むのつらいで諦めたのかも）
漁っていくうちに、初めのうちはどうやら[このサイト][SVG Tutorial]を見ながら[このサイト][w3schools]で気になったところを学びつつ、ここのTry it yourserfでプレイグラウンド的に動かしてみて細かいところはMDNや検索で詰めるのがいいのかなと思った
## svg特有のあの先の丸い線は、プロパティによって実現できるらしい
何かしらのプロパティとかがあるんだろうなーと思いつつも、実はイラストレーターからの直書きだったらどうしよう...と思っていましたが、普通に[プロパティでもあるようです](https://www.w3schools.com/graphics/svg_stroking.asp)（linecapって言うらしい）
例

```xml
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="64" height="64"
   stroke="black" stroke-width="2" stroke-linecap="round">
  <line x1="2" y1="12" x2="22" y2="12"/>
</svg>
```

ただまぁ、実際にはこういうのもpathで書かれてることのほうが多い気がするかも...そんなにたくさん見たわけじゃないけど。まぁそういうのは冗長になりがちっぽいし、機械から吐くなら極力情報を圧縮できるパスのがいいんだろうねぇ
もしくは最適化するやつとか使っててそれで全部パス化されてるとか。（実際試してみたらされはした）いや、見た目的にそういうわけでもなく普通に最初からパスで出力されてるののが多そう。FontAwesomeとかが顕著な気がする
また、線の繋ぎ目？の部分も角丸にするには`stroke-linejoin="round"`というのを追加で指定すればいいっぽいです。実のところ自分もまだ使ってなくてよくわかってないけど、[iconsvg.xyz]のオプションのところがわかりやすいと思う
パスで直書きされがちとは言っても先に挙げたやつのようにpath要素に対しても適応できるので、それ一つで手軽に角丸にしたりとか直角にしたりとかできるのはいい点だと思われる（今見てみるとそういうのも三分の一から半分ぐらいの割合でありそう）
てな感じで使われてるかどうかでいうと微妙そうではあるけど、こういうありがちなやつがマークアップ的にシンプルに描けるのは嬉しい

## パスをいじりたいなら、いい感じの[パスエディタ]があったのでそれがよさそう
そもそもパスってなんぞや？って話ですが、line要素で書くとこうなるやつ

```xml
<line x1="2" y1="12" x2="22" y2="12">
```
が、こうなるやつ

```xml
<path d="M 2 19 L 22 19"></path>
```
のことです。多分。
見ての通り、人間が読むことにはあまり重点を置いていなさそうな感じですね。その代わり柔軟性も高く、一要素で全てを描画しきることもできるなどもあり大抵はドローツールとかから吐き出されるものと思います
ただ、大抵のアイコン素材はこれを使って描画されています（lineとかcircleとかまで使ってるのはそれこそ[FeatherIcons]ぐらいしか知らないです。Fetherでも複雑なのとかはさすがにパスを使ってるぽいですし）

あと、lineなどの要素を使う際のように複数の要素を配置して重ね合わせていくのではなく、polyline等のように最初のMという始点から各命令を使用して数珠繋ぎのようにして描画されることが多いです（もちろん複数のパス要素を重ね合わせて描画することもできますし、色分けする際はfillとstrokeで区別しない限り分けることになると思いますが、アイコン作成ではM区切りのシングルパスで事足りると思われます）  

この例のようにシンプルなものならいいですが、イラレなんかから吐き出されたやつなんかは複雑だったりして読むのがつらいです
そもそも、柔軟な描画をしようとすればパスの使用は避けられません。例えば、月の形のアイコンを作ろうとすると（少なくとも私の知る限りでは）circle要素などでは対応できないと思われるため、パスを使うしかないでしょう。困りましたね？
そんな時のための[パスエディタ]です
このツールは上の例でいうところの`d=" "`の中身のやつを編集・解析するためのものと思われまして、ついでにMとかLとかの各要素についても何となく学べます
ちなみにこのエディタ上で作成したものはデフォルトでは要素名が全て大文字ですが、実際には小文字のやつもあったりします。どうやら[小文字だと相対パスで大文字だと絶対パスになる](https://developer.mozilla.org/ja/docs/Web/SVG/Tutorial/Paths)とか（よくわかってない）
### 大雑把な使い方
それはともかく、このパスエディタの使い方としては

- 左上のバツボタン（クリア）を押して邪魔な初期絵を消す
- ズーム度を調整したい場合はスクロールする
- 左上プラスボタンから新しい要素を追加する
	- まず最初は基準点(M要素, Move to)を追加することになると思う
- 要素の終点をクリックして選択状態にすると三点ボタンが出るので、そこからいろいろと操作できる
	- Insert After（プラスボタン）でその後に各要素をつなげる
	- Convert To（矢印のやつ）で別の要素に変換できる（状態が維持されるわけではなくあくまで同じ位置に別の要素を置く、というものと思っておいたほうがいいかも。Line→Vertical, Horizontalならわりとうまくいく）
	- Set Relative/Set Absolute（同上）で絶対パスと相対パスを相互変換できる。（左側のConvert toで全体の全体の変換も可）
		- 各値が大きい場合なんかだとこれをすることでデータを小さく＆可読性を高くできるのかも
	- Delete（ゴミ箱）はそのまま。削除
	- ちなみに画面左下Commands以下の各要素左側の三点メニューからも同じ操作ができるっぽい
- ConfigurationのShow TicksとMinify outputはオンにしておいた方が使い勝手がよさそう
- 同じくConfigurationのPreviewを使う際にはFillがオンだと線が見えないと思うので注意（囲まれたところが黒塗りで表示される）。基本的にはオフにしといていいと思う
- 細かく調整したい場合はCtrl+ドラッグが使えそう
- 左上保存ボタン（フロッピーのやつ）で現在のパスをlocalStorageに保存できる
- 開くボタン（フォルダのやつ）で保存したパスを開ける
- それらの上にあるPathテキストエリアからパスとしてコピー・編集できる
- 右上ダウンロードボタンでsvg画像としてエクスポートできる

といった感じ。あとはおおよそ見た通りだと思います
私はこれをいじることによりパス要素の概観がなーんとなくわかりました
ちなみになんですが、パスエディタじゃない普通のドローツールで気軽に使えそうなウェブツールないかなーとも思ったのですが、どうやら画面サイズを調整したりする必要があったりでこのようなシンプルでドット絵的な描き方をするには面倒くさそうだったので、それならこのパスエディタでいいかなーと思い諦めました。まぁ結果的にこれでほぼ満足できたというのも大きいけど
stroke-linejoinを知らなかった際はかなりうーんって感じでしたが、（linecapで全て解決できると勘違いしていた）それとさえ知ってしまえば「もうこれでいいじゃん」ってなりました
### ただし、曲線は難しい
ドローツールのように強力なサポートを得られるわけではないので、（人力でカーブ調整するには限界があるし、計算するのもめんどくさい）自由に曲線を描くのは面倒そう
単純な半円ならデフォルトのA要素(Arc?)の設定で簡単にできるのでまだしも、それ以外の形、例えば切り欠きのある円となると少なくともマウスポチポチだけじゃかなり厳しい
だとしてもCurve計算三昧は嫌なのでA要素[^2]に頼ることに（うまくいっている例を目にしたので）
...???（検索結果を見ながら）全く分からない（疲れていたので日本語ロケールで検索したのだが、[これ（参照1）](https://triple-underscore.github.io/SVG11/paths.html#PathDataEllipticalArcCommands)とか[これ（参照２）](http://yamatyuu.net/computer/html/svg/arc.html)とかのむつかしいやつしか出てこなかった...）
まぁ、これらの資料に加えとりあえずちょっと触ってみてわかったのをまとめてみると
・パラメータ一覧（超大雑把）

| 要素名       | rx         | ry         | x-axis-rotation              | large-arc-flag | sweep-flag   | x    | y   |
|:------------:|:----------:|:----------:|:----------------------------:|:--------------:|:------------:|:----:|:---:|
| 日本語でおｋ | 楕円縦半径 | 楕円横半径 | xとyが違う時になんかするやつ | 大なりか否か   | 右回りか否か | 始点 | 終点|


- そもそもA(Arc?)は楕円弧曲線を描く命令であり、rx ryはそれぞれの楕円の半径。楕円ではなく円を描く限りはとりあえずは同じにして全体の円の半径と思ってよさそう。よってx-axis~は無視
- 始点及び終点となる二つの点が与えられた際、それを通過すると予想される楕円は大回りの楕円と最小距離の楕円の二つがあるが、large-arc-flagは大回りかどうかを0/1で判断するフラグ
	- たぶん円に限って言えば同じ径の二つの円を組み合わせて「どっちも通過するよねー」ってなってるイメージ。参照2にいい感じの図があった
	- どういうことかは知らないが、値が直径以上になると常にこのフラグと関係なく半円状になる（x to y = rで二つの円が完全に同化するから、それが維持されている？）
	- 半径以下の数値の場合には、large-arc-flagの値に応じて大きいほうを通過するか小さいほうを通過するかが決まる（この分岐にはsweep-flagも干渉するが、sweep-flagに関しては適宜切り替えればいい話で見ればわかると考え詳細は省いた）
- このパスエディタのrx及びryの初期値は1なのが理解をややこしくしている気がする。試しに新しくArc要素を1x1で作って、左下のlarge-arc-flagを切り替えてみれば「そういうことだったのか！」となるかもしれない

よって、恐らくではあるけど多分**rxとryに想定する半径を入力してlarge-arc-flagにチェックを入れ、なんやかんやすればたぶんいける**という結論に至った
俄然として大雑把ではあるが、なんとなくの理解は得られたと思う。めちゃくちゃ時間と精神的コストは取られたけど[^3]。なんてこったい...
ちなみにこれによって月のアイコンの例を作成することに成功したので載せておきます

```xml
<svg viewBox="-1 -1 24 24" width="64" height="64" stroke-linecap="round" stroke-linejoin="round" stroke="black" 
   fill="none" stroke-width="1">
  <path d="M5 0A5 5 0 1010 5A1 1 0 015 0"/>
</svg>
```

## 私の使っている雛型
参考までに私の使っている雛型を載せておきます

```xml
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
  <g id="square" stroke-width="0.1" fill="none">
    <path id="base-square" d="M2 2L22 2L22 22L2 22L2 2z" stroke="#FF0000"/>
    <path id="long-width" d="M1 3L23 3L23 21L1 21L1 3z" stroke="#00FFFF"/>
    <path id="long-height" d="M3 1L21 1L21 23L3 23L3 1z" stroke="#FFFF00"/>
    <path id="circle" d="M12 1A1 1 0 0012 23 1 1 0 0012 1z" stroke="#00FF00"/>
  </g>
  <g id="main" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
    <path d=""/>
  </g>
</svg>
```
最後のpath要素の中に任意のパスを入れられるようにしてあります
[FetherIconsのもの](https://github.com/feathericons/feather/issues/171#issuecomment-455356985)を参照し、[こちらのガイドライン](https://blog.nucleoapp.com/nucleo-icon-guidelines-introduction-70092f8b4697#5b81)にあるような設計を反映した背景を指定しています（色がやけにカラフルなのは仮のものなので勘弁してご自分で調整してください...）
あと、できる限りその他の線の中に収めたほうが良いと考え一番外周の線は省いています（以下のパスエディタ用のものでは含む）

パスエディタ用のシングルパス（単色、左上のとこに貼り付ける用）

```
M0 0 24 0 24 0 24 24 0 24 0 0ZM2 2 22 2 22 22 2 22 2 2ZM1 3 23 3 23 21 1 21 1 3ZM3 1 21 1 21 23 3 23 3 1ZM12 1A1 1 0 0012 23 1 1 0 0012 1z
```

## 結論
- とっかかりにはいいと思うけど、それでもテキストエディタのみではちょっときつそう（いちいち細かな計算が必要になるので調整したり試行錯誤したりが面倒そう）
- パスエディタがあれば割となんとかなる
- こんな調べるぐらいならドローツール使ったほうが楽だった気がせんでもない
- あと、最初は[SVG Tutorial]を読んでたものの途中からなぜかつらくなって他のやつに浮気し始めてたんだけど、あらためて見てみるとアイコンっぽい感じのノウハウや例もあったりでこのチュートリアルがやっぱ優秀なことに気づいた。ただ、数字を見て脳内にグリッドを再現しながらだとやはりきついので、パスエディタ片手に見るのがおすすめ

## 参考（便利リンク集）
[パスエディタ](https://yqnn.github.io/svg-path-editor/)
[awesome-svg](https://github.com/willianjusten/awesome-svg) - あるかなーと思ったら案の定あった
[awesome-icons](https://github.com/vkarampinis/awesome-icons) - なぜかあまりスターが多くないけどあった。参考になりそうなのやそのままでも実用できそうなのがいっぱい
[iconsvg.xyz] - 多分自作するにあたっては一番参考にしやすいと思う。ページ末尾に書かれた文を見る限りfetherを元にしているっぽい
[SVG Tutorial： How to Code SVG Icons by Hand][SVG Tutorial] - とりあえず見といていいと思う
[w3schools] - MDNよりも易しい感じのやつ。比較的とっつきやすいのと、Try it Youselfでその場ですぐに動かせるのが非常に嬉しい（プレイグラウンド的なやつなので、改変してみたり手元にあるのを動かしたりもできる）
[MDNのSVGチュートリアル](https://developer.mozilla.org/ja/docs/Web/SVG/Tutorial) - 前置きからして古そうではあるけど、まぁSVG自体最新版が2011年の案外古くからある技術みたいなわけだしSVGの中身を知るには悪くなさそう。
[MDNのSVGのページ](https://developer.mozilla.org/ja/docs/Web/SVG) - 個人的にこういうウェブ系の（興味の薄い分野の）よくわからん技術でも辛うじて学ぼうと思えるのはMDNのおかげ


[SVG Tutorial]: https://www.aleksandrhovhannisyan.com/blog/svg-tutorial-how-to-code-svg-icons-by-hand/
[パスエディタ]: https://yqnn.github.io/svg-path-editor/
[iconsvg.xyz]: https://iconsvg.xyz/
[FeatherIcons]: https://feathericons.com/
[w3schools]: https://www.w3schools.com/graphics/svg_intro.asp
[^1]: 主力。こいつで何とかならないところ（構文、言い回し、ガバ訳等）は頑張るしかないがそれだけでも弱者にはわりとつらい
[^2]: ちなみにだけど、path内のAとかLとかを要素って呼ぶのはたぶん正しくない。正確にはpath要素のd属性内のL(Line)命令、とかになるのだろうか
[^3]: 英語疲れで疲労困憊じゃなかったらここまでにはならなかったような気はする。わかってしまえばそこまで難しい話でもないし。ただ、あの状態で投げたら長いこと調べない日々が続きそうな気がしたもので...