SVG画像の特徴と注意点


## 本記事の目的

SVGについて基本的なことを理解できていなかったのでまとめてみる。


## SVG画像とは
- ベクターグラフィックス[^1]を描画する、XML形式の言語からなるファイル
- `<path>`で点の座標の位置、`<circle>`で円を表す要素が含まれている（他にも四角形を作成する`<rect>`などが存在する）
- ベクターグラフィックスであるため、拡大・縮小してもボヤけにくい
- 線・点などのデータの集まりであるため、写真などをSVG画像にするとデータ量が膨大になる


## SVG画像を使用する際の注意
- XML形式がゆえに、ラスター画像(jpgやpng)を埋め込むこともできるため、以下のようにSVGファイルの画像の一部がラスター画像になっていることもある [▶︎参考サイト(MDN)](https://developer.mozilla.org/ja/docs/Web/SVG/Reference/Element/image)

```html
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
  <image href="mdn_logo_only_color.png" height="200" width="200" />
</svg>
```


- `<path>`に記載されている数値が座標の位置を表すが、その数値の小数点以下の桁数が1桁だったりすると、綺麗に描画されないことがある（座標の位置が精緻でなくなり、正確な位置から遠ざかって表現されるため）[▶︎参考サイト](https://rikuo.hatenablog.jp/entries/2014/12/03)
- SVG画像なのにボヤけて見える場合、ぼかしを定義する`<filter>`が含まれていることがある[▶︎参考サイト(MDN)](https://developer.mozilla.org/ja/docs/Web/SVG/Reference/Element/filter)
- iOSで`<filter>`を含むSVG画像を読み込んだ場合、ボヤけて見えるバグがある模様? [▶︎参考Qiita](https://qiita.com/chrysalis/items/ab190bf6d1257610789a)
- XML形式がゆえにJavaScriptなども埋め込むことができるため、悪意のあるスクリプトが含まれていて表示した際に実行されてしまう場合がある（SVG画像をユーザーにアップロードさせてそのまま表示するのは危険。インラインで埋め込んでしまうとそのJavaScriptが実行される）[▶︎参考Qiita](https://qiita.com/itizawa/items/e98ecd67910492d5c2af)


## SVG画像の中身の詳細

### `<path>`

- d属性で、パスを定義する
    - 以下の例だと、MがmoveTo（起点）を表し、LはLineToの意味で終点を表している（多分）
- d属性値はいろんな書き方がある [▶︎参考サイト](https://developer.mozilla.org/ja/docs/Web/SVG/Reference/Attribute/d)


```
<path d="M 46.7,66.4
		 L 163.2,168.4"/>
```


### `<g>`
- グループ化を表すタグ
- `<g>`の中身をグループ化して、`<use>`で呼び出すことで繰り返し同じグループオブジェクトを使う、みたいなこともできる
    - 以下の例だと、`<g>`で定義されたグループを`doubleCircle`というid名をつけて、 `use`でそのid名を呼び出し、`stroke="green"`を定義することで緑線の円を表示できる

<p class="codepen" data-height="400" data-default-tab="html,result" data-slug-hash="pvvBdmd" data-pen-title="Untitled" data-user="nakonako" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/nakonako/pen/pvvBdmd">
  Untitled</a> by nako (<a href="https://codepen.io/nakonako">@nakonako</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://public.codepenassets.com/embed/index.js"></script>

### `<defs>`

- 一度オブジェクトに関する情報を定義しておくためのタグ
- 要素内に作成されたオブジェクトは直接レンダリングされない
- オブジェクトを表示するには`<use>` 要素などを用いて参照する必要がある
    - 以下の例だと`<use>`の一行を削除すると、表示されなくなる

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="NPPmXPj" data-pen-title="Untitled" data-user="nakonako" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/nakonako/pen/NPPmXPj">
  Untitled</a> by nako (<a href="https://codepen.io/nakonako">@nakonako</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://public.codepenassets.com/embed/index.js"></script>


### `filter`

- フィルターを定義する
- `<filter>`タグはレンダリングされない
- idをつけて、そのidをSVG要素のfilter属性などで使用することで描画される
    - 以下の例だと、`blurMe`というid名をつけ、`circle`タグのfilter属性値にそのid名を記述することで`circle`タグの円にフィルターをつけられる

```
<svg width="230" height="120" xmlns="http://www.w3.org/2000/svg">
  <filter id="blurMe">
    <feGaussianBlur stdDeviation="5" />
  </filter>

  <circle cx="170" cy="60" r="50" fill="green" filter="url(#blurMe)" />
</svg>
```

[▶︎参考](https://developer.mozilla.org/ja/play)




[^1]: 点の座標とそれを結ぶ線（ベクター、ベクトル）などの数値データをもとにして演算によって再現された画像のこと