SVGについて

## はじめに

自分の周りにはPHPエンジニアが多いので、フロントサイドの情報が珍しがられます。

たまに開かれる勉強会でSVGを題材にしたところ、わりと受けが良かったので、Qiitaにも展開したいと思い投稿しました。

間違っている部分やわかりにくいところもあるでしょうが、ゆるく見ていただくと嬉しいです。

## SVGとは

SVGは、HTMLなどのWEBで使用される画像形式として認識されることが多いと思いますが、ただの画像形式ではなく、興味深い特徴があります。

その一番大きな特徴はベクターグラフィックであるということです。

ベクターグラフィックは座標とそれをつなげるパスを元にした、図形を表現するのに適した形式です。
座標の情報が元なので、拡大しても画像が荒れないという特徴があります。

更に、xmlテキスト形式で記述されているため、テキストエディターで編集が可能で、CSSやJavaScriptが埋め込めたりします。

## ベクターグラフィックスとラスターグラフィックス

ベクターグラフィックは「座標を元にした絵」に対してラスターグラフィックは「ピクセルを元にした絵」です。
一般的に、写真などのデータは、ピクセルの集まりで表現されるラスターデータになります。

他方、ベクターグラフィックは、ロゴやピクトグラムのような単一の色で構成された面の組み合わせで作成された図形に向いており、複雑なグラデーションや色の数が多いものには向きません。

### 比較

| ベクター画像 | ラスター画像 |
| ------------ | ------------ |
| 拡大縮小しても品質が劣化しません。 | 拡大すると画質が劣化しピクセルが目立つようになる。 |
| どんなサイズでも鮮明さを保ちます。 | 縮小すると細部が失われます。 |
| 単純な図形の場合ファイルサイズが小さくなる傾向。 | 画像の解像度と色深度でファイルサイズが決まる。 |
| 複雑になるほどファイルサイズが大きくなります。 | 高解像度の画像は大きなファイルサイズになります。 |
| 個々の要素を独立して編集できます。 | ピクセル単位での編集が必要です。 |
| 形状や色を簡単に変更できます。 | 大きな変更を加えると品質が低下することがあります。 |
| ファイル形式: SVG, AI, EPS, PDF | ファイル形式: JPEG, PNG, GIF, TIFF, BMP |

### ラスター画像の得意なこと

ラスター画像は、ピクセルの集まりで画像を表現しています。
ピクセル単位で配色してデータが構成されているので、色の数が多い画像に向いています。
例えば、写真のように少しづつ違う色が隣り合うようなものや、グラデーションが多用されているイラストなど、色の多いものを表現するのに適しています。

画像をピクセルで表現するので、拡大すると画像としてのクォリティーが下がってしまいます。

#### 拡大するとピクセルが見えるようになる

![raster01_1-80.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34376/794a42eb-79c4-49c1-8908-fc8f1f578c65.jpeg)

#### 複雑なグラデーションや色の多い画像

![AdobeStock_339045266.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34376/55c2ec89-3b89-4de9-b87b-4fd744cb1718.jpeg)

### ベクター画像の得意なこと

ベクター画像は、座標と面で画像が表現されるので拡大・縮小で画像が劣化しません。
ピクセルで表現するわけではないので大きさに影響がないわけです。

逆に、複雑なグラデーションなどの色の数が多いものを表現しようとすると、一色につき一オブジェクトが必要になるので極端に容量が大きくなることもあります。（単純なグラデーションの場合は<linearGradient>や<radialGradient>タグが使用できます）
また、ラスターグラフィックスを埋め込むこともできますが、あまり見かけません。
ラスターグラフィックスを埋め込むようなら元からラスターグラフィックスにするということなのでしょう。

![vector01-80.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34376/7da63be0-db88-4b0f-bcfe-cb4cb7786122.jpeg)

## HTMLで使用するSVGファイルと`<svg>`タグ

SVG画像は、JPEGやPNGなどの画像ファイルのようにHTMLの`<img>`タグで記述可能です。

`<img src=”/images/sample.svg”>`のように記述ができます。

HTML内に直接書き込むこともできます。
```html
<svg xmlns="http://www.w3.org/2000/svg" 
    width="22px" height="20px" viewBox="0 0 22 20">
<path fill-rule="evenodd"  fill="rgb(255, 72, 0)"
 d="M11.081,20.002 C11.081,20.002 28.353,6.934 19.461,1.032 C14.332,-2.372 10.994,3.762 10.994,3.762 C10.994,3.762 7.655,-2.372 2.526,1.032 C-6.366,6.934 11.081,20.002 11.081,20.002 L11.081,20.002 Z"/>
</svg>
```

## SVGの構造
SVGの中身はXMLで記述されています。
基本的な図形は、rect（長方形）、circle（円形）、line（直線）などの命令がありそれぞれのパラメータを設定することで描画されます。
```html
<svg width="160" height="160" viewBox="0 0 160 160">
     <rect x="0" y="0" width="160" height="160" fill="skyblue" />
     <circle cx="80" cy="80" r="40" fill="gold" />
     <circle cx="65" cy="75" r="5" fill="black" />
     <circle cx="95" cy="75" r="5" fill="black" />
     <line x1="65" y1="95" x2="95" y2="95" stroke="black" stroke-width="5" stroke-linecap="round" />
</svg>
```
## SVGオブジェクトの記述例

|オブジェクト| 記述例 |
| ------------ | ------------ |
| 長方形 |`<rect x="10" y="10" width="100" height="50" fill="blue" />` |
| 円 | `<circle cx="50" cy="50" r="40" fill="red" />` |
| 楕円 | `<ellipse cx="100" cy="50" rx="70" ry="40" fill="green" />` |
|直線|`<line x1="10" y1="10" x2="90" y2="90" stroke="black" stroke-width="2" />`|
|折れ線|`<polyline points="10,10 30,30 10,50 30,70" fill="none" stroke="purple" />`|
|多角形|`<polygon points="50,10 90,90 10,90" fill="yellow" />`|
|自由曲線や複雑な図形|`<path d="M10 10 L90 90 L90 10 Z" fill="orange" />`|
|テキスト|`<text x="20" y="35" font-family="Arial" font-size="24" fill="black">Hello SVG</text>`|

## HTMLで使用するSVGファイルと`<svg>`タグ

ファイルとして利用する場合が多いように思います。
大きさ（width,height）は、タグ内に記述しますが、CSSで指定することが多いように思います。
ただし、SVGの中のオブジェクトをCSSやJavascriptで変更したいときにはインライン要素としてHTMLに記述する必要があります。
objectタグで埋め込むとCSSで変更できますが、CSSの指定方法、レスポンシブの際の大きさ変更など、少し特殊です。
このことから、ベクターデータをアニメーションするなどの目的がないのであれば、ファイルとして利用するのがいいでしょう。

## SVGの作成について
色々な作り方があるでしょうが、多くの場合、Illustratorで作成するのではないでしょうか？
図形を書いて、コピーするとクリップボードにSVGとして保存されるので手軽です。

また、図形やイラストを選択してSVGに書き出すことができます。
ただし、SVGに動きをつけたい場合は、その構造を理解してSVGファイルの中のどのパーツについてアニメーションさせるかを検討しなければなりません。
そのためには、基本的な構造を理解する必要があります。

### SVGの実装

もう少し詳しく見てみます。
SVGはhtmlに記述する場合、下記のようにします。

注目してほしいのは、`<svg...`で始まるSVGタグのパラメータです。
SVGは既成のものを使用する際にはあまり意識しないと思いますが、width・heightとviewBoxの関係がわかりにくく、僕にとっては理解に時間がかかりました。

```html
<!DOCTYPE html>
<html lang="ja">
 <head>
   <meta charset="UTF-8" />
   <title>Document</title>
 </head>
 <body>
   <svg width="160" height="160" viewBox="0 0 160 160">
     <rect x="0" y="0" width="160" height="160" fill="skyblue" />
     <circle cx="80" cy="80" r="40" fill="gold" />
     <circle cx="65" cy="75" r="5" fill="black" />
     <circle cx="95" cy="75" r="5" fill="black" />
     <line x1="65" y1="95" x2="95" y2="95" stroke="black"
stroke-width="5" stroke-linecap="round" />
   </svg>
 </body>
</html>
```

### SVGのサイズとViewBox

SVGの記述で最初につまずくviewBoxは、widthとheightとの関係が設定を複雑にしています。

viewBoxは、左上の座標、右下の座標の順にそれぞれx,yを書きます。

widthとheightで指定した長方形をどの大きさとして扱うか・・・というように考えると良いでしょう。

```html
<svg width="160" height="160" viewBox="0 0 160 160">
```
![スクリーンショット 2025-05-19 18.44.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34376/83a36932-d521-4b68-9e2f-12235b674f0f.png)

```html
<svg width="160" height="160" viewBox="0 0 80 80">
```
![2025-05-19 18.44.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34376/af632e2e-c888-46f6-afa5-a257d55875a8.png)

```html
<svg width="160" height="160" viewBox="0 0 320 320">
```
![スクリーンショット 2025-05-24 14.14.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34376/3d96faa2-1a78-4b0d-b9f3-f9897c51134c.png)

## 終わりに

svgについては、まだまだ書くことがありそうですが、今回はここまでといたします。

ここまで読んでくれた方に感謝します。