SVGの扱い方

SVGはScalable Vector Graphicsの略です。

## ビットマップ画像(jpegやpngなど)との比較

### SVGのメリット
- 拡大しても画像が荒れない(スマホなど高解像度の表示に強い)
- 単純な形状のものは容量が小さくなる

### SVGのデメリット
- 写真や手書きのイラストなど色や形状が複雑な画像には不向き


## SVGでできること
- 図形やテキストの表示
- グラデーション
- テキストの表示
- マスク、クリップ
- フィルター
- ビットマップ画像の表示

## ブラウザで表示されない時の対応
サーバーによってはブラウザー側で.svg、.svgzを画像として認識してくれないので.htaccessに以下を追記します。

```:.htaccess
 AddType image/svg+xml .svg
 AddType image/svg+xml .svgz
```


## SVGの作成
### コードを記述してSVGを作成する
エディタを使用し、コードを記述してSVGを作成します。

### ツールを使用してSVGを作成する
[Adobe Illustrator](https://www.adobe.com/jp/products/illustrator.html)、[Affinity Designer](https://affinity.serif.com/ja-jp/designer/)などのアプリを利用します。
[Vecteezy](https://www.vecteezy.com/editor)　オンラインのエディタを使うことも出来ます。
[ZorroSVG](http://quasimondo.com/ZorroSVG/)　透過のPNGやGIFファイルをアップロードし、透過SVGファイルを生成することも出来ます。

### 作成時に気を付ける事
- アイコンなどに使う場合は、「100px × 100px」のように正方形で作成
- 高さがいっぱいになるように作成
- テキストデータなどを使っていたり、複雑な形状の場合はアウトライン化する
- 色を変える場合にはCSSで変更しやすいように一色のオブジェクトにしておく
- IEではファイル内にwidthとheightを指定する必要がある

## 軽量化

### SVGOMGで軽量化する
[SVGOMG](https://jakearchibald.github.io/svgomg/)

|項目|意味|
|---|---|
|Remove doctype|DOCTYPE宣言を削除|
|Remove XML instructions|XML宣言を削除|
|Remove comments|コメントを削除|
|Remove <metadata>|metadataを削除|
|Remove xmlns|xmlnsを削除|
|Remove editor data|エディタデータを削除|
|Cleanup attribute whitespace|空白の属性を削除|
|Inline styles|インラインスタイル|
|Minify styles|Styleをminify|
|Style to attributes|Styleを属性にする|
|Clean IDs|IDをクリーンにする|
|Remove raster images|ラスター画像(ビットマップ画像)削除|
|Remove unused defs|未使用の定義を削除|
|Round/rewrite numbers|数値を丸める/書き換え|
|Round/rewrite number lists|数値リストを丸める/書き換え|
|Minify colours|色をminify|
|Remove unknowns & defaults|不明なもの、省略可能なものを削除|
|Remove unneeded group attrs|不要なグループ属性を削除|
|Remove useless stroke & fill|不要なstrokeとfillを削除|
|Remove viewBox|viewBoxを削除|
|Remove/tidy enable-background|enable-background属性の削除/整理|
|Remove hidden elements|非表示の要素を削除|
|Remove empty text|空のテキストを削除|
|Shapes to (smaller) paths|より小さいパスにする|
|Move attrs to parent group|属性を親グループに移動|
|Move group attrs to elements|親グループの属性を要素に移動する|
|Collapse useless groups|未使用のグループを潰す|
|Round/rewrite paths|pathを丸める/書き換え|
|Round/rewrite transforms|transformsを丸める、書き換え|
|Remove empty attrs|空の属性を削除|
|Remove empty containers|空のコンテナを削除|
|Merge paths|pathを結合|
|Remove unused namespaces|未使用のnamespaceを削除|
|Sort attrs|属性をソートする|
|Remove <title>|titleを削除|
|Remove <desc>|descを削除|
|Prefer viewBox to width/height|width,heightよりviewBoxを優先|
|Remove style elements|style要素を削除|
|Remove script element|script要素を削除|


### 手動で軽量化する場合
#### 不要部分を削除する
SVGをエディタで開き、上のSVGOMGのfeaturesの表を参考に、doctype宣言、xml宣言などを削除します。

#### path化
line, polyline, polygon 要素を使っている場合はpath要素に変換すると軽量化出来ます。

例：polygonとpolylineをpathに変換する方法
```points ="```を```d ="M```に変更します。
< polygon>は、最後の点を最初の点に接続するために、d属性の最後の文字としてzを追加します。

```:svg
<polygon points="1,2 3,-4 5,6"/> 
```
↓

```:svg
<path d="M1,2 3,-4 5,6z"/> 
```


### SVGの最小構成

```:svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 300">
  ...
</svg>
```

##### xmlns
HTMLに埋め込むことだけを考えると```xmlns="http://www.w3.org/2000/svg"```も削除できますが、厳密なSVGでは無くなってしまいます。

##### width,height
IE11でwidth,heightを指定していないSVG画像をbackgroundに指定すると、background-sizeで指定したサイズよりも小さく表示されてしまうので、IE11で使用する場合は追記が必要です。


## SVGの使用
SVGは読み込み方によって扱い方を変える必要があります。

### 表示する
#### 1.外部ファイルとして読み込む
画像要素となるので、SVGタグ内のpathに対してCSS, JavaScriptが効きません。

```:html
<img src="test.svg">
```

#### 2.背景画像として読み込む
画像要素となるので、SVGタグ内の要素に対してCSS, JavaScriptが効きません。

```:html
<div class="test"></div>
```

```:css
.test{
  background-image: url("test.svg");
}
```

#### 3.インラインに記述
SVGタグ内の要素に対してCSS, JavaScriptが効きます。

```:html
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
  <circle cx="50" cy="50" r="50"/>
</svg>
```

#### 4.object要素で読み込む
iframeのように別documentになるので、CSS, JavaScriptはそのdocumentに対して適用させる必要があります。

```:html
<object type="image/svg+xml" data="test.svg"></object>
```




### レスポンシブ対応

#### 1.外部ファイルとして読み込んだ場合
##### svgタグにwidthとheightを指定していない場合
imgタグで読み込むだけです。

```:html
 <img src="svg.svg" alt="">
```

##### svgタグにwidthとheightを指定している場合
jpegやpngと同様の方法です。

```:html
<img src="/svg.svg" class="imgResponsive">
```

```:css
.imgResponsive{
  width: 100%;
  height: auto;
}
```

#### 2.背景画像として読み込んだ場合

```:html
<div class="wrapper">
  <div class="svgBackground">
    <div class="content">
    </div>
  </div>
</div>
```

```:css
.wrapper {
  position: relative;
  width: 100%;
  background-color: gray; /* 背景色 */
}
 
.wrapper:before {
  content: "";
  display: block;
  padding-top: 75%;　/* 使いたい背景SVGの縦横比によって調整 */
}
 
.svgBackground {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  background: url("svg.svg") no-repeat;
  background-size: 100% auto;
}
```

#### 3.インラインに記述した場合
##### IEは対応不要な場合
svgタグにwidthとheightを指定しないだけでレスポンシブになります。

##### IEも対応が必要な場合

```:html
<div class="svg-wrapper">
  <svg  xmlns="http://www.w3.org/2000/svg" width="400" height="400" viewBox="0 0 400 400">
    <circle cx="200" cy="200" r="200" fill="#ccc" />
  </svg>
</div>
```

```:css
.svg-wrapper {
  position: relative;
  padding-top: 100%; /* SVG高さ / SVG幅 * 100 */
}

.svg-wrapper svg {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}
```

#### 4.object要素で読み込んだ場合
objectタグにwidthとheightを指定しなければそのままレスポンシブになります。

```:html
<object type="image/svg+xml" data="svg.svg"></object>
```





### 色変更
#### 1.外部ファイルとして読み込んだ場合
imgタグでの読み込みは色変更できません。


#### 2.背景画像として読み込んだ場合
背景画像なので CSS の fill プロパティや stroke プロパティは適用されません。
色指定変更の例：fill="#000000"を'%23000000'に変更する(16 進数表記の場合)
※全体を「"」で囲っている場合、各属性値を「"」で囲わないで「'」で囲うように変更するのを忘れないようにします。

##### IE対応が不要な場合

```:css
.class {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg'><circle cx='100' cy='100' r='100' fill='%233498db'/><circle cx='500' cy='300' r='100' fill='%23f1c40f'/><rect x='100' y='100' width='400' height='200' fill='%23e74c3c'/></svg>"); 
}
```

##### IE対応が必要な場合
色指定の先頭の%23を#に戻します。
「data:image/svg+xml;utf8」を「data:image/svg+xml;charset=utf8」に変更します。
```<svg>~</svg>```の部分をURLエンコードして置換する( https://www.tagindex.com/tool/url.html )

エンコード前

```:svg
<svg xmlns='http://www.w3.org/2000/svg'><circle cx='100' cy='100' r='100' fill='%233498db'/><circle cx='500' cy='300' r='100' fill='%23f1c40f'/><rect x='100' y='100' width='400' height='200' fill='%23e74c3c'/></svg>
```

エンコード後

```:svg
%3csvg%20xmlns%3d%27http%3a%2f%2fwww%2ew3%2eorg%2f2000%2fsvg%27%3e%3ccircle%20cx%3d%27100%27%20cy%3d%27100%27%20r%3d%27100%27%20fill%3d%27%233498db%27%2f%3e%3ccircle%20cx%3d%27500%27%20cy%3d%27300%27%20r%3d%27100%27%20fill%3d%27%23f1c40f%27%2f%3e%3crect%20x%3d%27100%27%20y%3d%27100%27%20width%3d%27400%27%20height%3d%27200%27%20fill%3d%27%23e74c3c%27%2f%3e%3c%2fsvg%3e
```

最終形

```:css
.class{
  background-image: url("data:image/svg+xml;charset=utf8,%3csvg%20xmlns%3d%27http%3a%2f%2fwww%2ew3%2eorg%2f2000%2fsvg%27%3e%3ccircle%20cx%3d%27100%27%20cy%3d%27100%27%20r%3d%27100%27%20fill%3d%27%233498db%27%2f%3e%3ccircle%20cx%3d%27500%27%20cy%3d%27300%27%20r%3d%27100%27%20fill%3d%27%23f1c40f%27%2f%3e%3crect%20x%3d%27100%27%20y%3d%27100%27%20width%3d%27400%27%20height%3d%27200%27%20fill%3d%27%23e74c3c%27%2f%3e%3c%2fsvg%3e");
}
```

#### 3.インラインに記述した場合
CSSで色変更が可能ですが、一部のプロパティがHTMLへの指定と違います。

- background-colorの代わりにfillを使う
- borderの代わりにstrokeを使う

インラインSVG内の色の色変更は、要素へのclass追加でも可能です。



#### 4.object要素で読み込んだ場合
JavaScriptで色変更が可能です。