SVGについて理解が曖昧なあなたへ

皆さん**SVG**についてしっかり理解・使用できていますか？
私は何度かSVGを学んだ後、正直感覚で使用してしまっているような気がします。

SVGはいわゆる画像の形式などでよく目にしますが、私自身も今まで複雑な使い方はしたことない為、一緒にSVGの「**可能性**」について知っていきましょう！

::: note
本記事は主に以下の方が対象になるかと思います。
- SVGについて理解が曖昧な方
- 何をできるのか知りたい方
- 他の拡張子との比較をしたい方
- SVGアニメーションに興味を持っている方（現状の私）
:::



本記事含めアドカレ後半戦も記事をぼちぼち投稿していきますので、ぜひ読んでいただけたら嬉しいです:raised_hand:

よろしくお願いします〜

## SVGとは
![img_svg01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624902/38f80fca-13d9-b23c-6006-b6a75b47b665.png)

### SVGは何かを簡単に言うと
SVG (スケーラブル・ベクターグラフィックス)は、XMLベースのファイルフォーマットで、ベクター画像として定義されています。このファイルフォーマットは、画像をピクセルやライン、シェープで表現するのが特徴で、「解像度に依存せず高画質の回路を持つ」画像です。

また、テキストエディタで編集が可能で、「画像の細部を直接制御」することができます。そのため、デザイナーや開発者にとって、柔軟性のあるフォーマットとして広く活用されています。

すでにここまででかなり有用なのが伝わっているのではないかと思います。

### SVGの歴史
SVGは、1999年にW3C (World Wide Web Consortium)により初めてスタンダードとして提供されました。その後、Webプラットフォームの発展と共に実用化され、今では多くのブラウザでネイティブサポートを受けています。

特に、スマートフォンや高解像ディスプレイの普及に伴い、SVGは解像度に依存しない特性が評価され、ロゴやアイコンの表示においてよく使用されるフォーマットになっています。

## SVGと他フォーマットとの違い

### 具体的な違い

**ベクターとラスター**
![img_svg02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624902/441022a4-dcab-131e-5cd9-4162c85000fd.png)

SVGはベクター画像ですが、JPGやPNG、GIF、WebPはラスター画像です。これは、SVGが数学的な計算に基づくベクター形式で拡大縮小に強いのに対し、他の形式はピクセルで構成されるため、拡大すると画質が劣化します。

:::note
**なぜピクセル化すると画質が劣化しやすいのか？**
ピクセル＝絶対値、すなわちそれ以上分割できない単位となります。したがって、例えばピクセル化すると拡大時は1つのピクセルを引き伸ばすことになります。その結果、単に引き伸ばしただけなので、その分粗く見える現象が発生してしまうという訳です。
:::


**アニメーションの対応**

SVGはCSSやJavaScriptを使ってアニメーションを作成できます。他にもGIFやWebPはラスター形式のアニメーションを直接サポートしており、こちらは特に短いアニメーションや動画で効果的に使用されます。

**ファイルサイズと圧縮**

SVGは、ベクター形式であり、複雑な形状やデザインを少ないデータ量で表現できるため、特に単純なアイコンやロゴでは他の形式に比べてファイルサイズが非常に小さく抑えられます。

### それぞれの選択場面（一部フォーマットをピックアップ）

- **SVG**
  - ロゴデザインやアイコン
  - Webアニメーション
  - ユーザーインターフェース
  - 解像度を問わないグラフィック
- **JPG**
  - 写真や自然なイメージ
  - 大量の画像が必要なWebサイト
- **PNG**
  - 透過が必要な画像
  - 高画質が求められる静的画像
- **GIF**
  - 簡単なアニメーション
  - ソーシャルメディアでの利用
- **WebP**
  - ファイルサイズを最小化しつつ高画質を保つ必要がある場合
  - 次世代フォーマットをサポートする環境

:::note
GoogleのSEO的にはWebPが推奨されていて、例えばPageInsightなどでWebサイトのパフォーマンスを分析するときにはWebPじゃないと怒られることがあります。
それも関係してなのか、タスクランナーやJS関連の画像フォーマット変換ライブラリなどが多数存在するイメージがあります。
:::

### 選択に迷う場面

これらの形式を使い分ける際には、主に以下の点に注意してください。

- 画像の用途（Webか印刷か）
- 必要な画質
- ファイルサイズとロード時間
- アニメーションの必要性

### 章内の内容まとめ

| フォーマット | 特徴           | 適した用途                 |
| ------ | ------------ | --------------------- |
| SVG    | ベクター形式、高解像度対応 | ロゴ、アイコン、Webアニメーション    |
| JPG    | ラスター形式、高圧縮率  | 写真、自然なイメージ            |
| PNG    | ラスター形式、透過対応  | 高品質画像、透過が必要な場面        |
| GIF    | ラスター形式、アニメ対応 | 短いアニメーション             |
| WebP   | 高圧縮率、次世代形式   | 高画質で軽量化が必要な画像、アニメーション |

## SVGで何ができるか

### SVGで何ができるか
- ロゴデザインやアイコンの作成
- アニメーションやインタラクティブデザインの実現
- Webブラウザでの高解像表示
- データビジュアライゼーションやインフォグラフィックスの作成
- 印刷可能なベクターアートの作成

### SVGはコードとしても扱える
#### **コードでの形状・デザインの設計**
```html
<svg width="100" height="100">
    <circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
</svg>
```
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="JoPbpVQ" data-pen-title="svg_demo01" data-preview="true" data-user="nunllunb-the-reactor" 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/nunllunb-the-reactor/pen/JoPbpVQ">
  svg_demo01</a> by Saku (<a href="https://codepen.io/nunllunb-the-reactor">@nunllunb-the-reactor</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

このコードは、赤い円とそれを囲む黒い線を描画します。
- シンプルな形状を直感的に描くことができます。
- 例: 「&lt;circle&gt;」や「&lt;rect&gt;」タグで簡単に形状を表現

#### インタラクティブな動きをCSSやJavaScriptで描く
CSSやJavaScriptを使うことで、この円を動かすことも可能です。

##### JavaScriptでのアニメーション
```html
<svg width="120" height="120">
    <circle id="myCircle" cx="60" cy="60" r="50" stroke="black" stroke-width="3" fill="red" />
</svg>
```
```javascript
const circle = document.getElementById('myCircle');
let position = 0;
let direction = 1;

function animate() {
  position += direction * 2;
  if (position > 50 || position < -50) direction *= -1;
  circle.setAttribute('cx', 60 + position);
  requestAnimationFrame(animate);
}
animate();
```

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="vEBydqL" data-pen-title="Untitled" data-preview="true" data-user="nunllunb-the-reactor" 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/nunllunb-the-reactor/pen/vEBydqL">
  Untitled</a> by Saku (<a href="https://codepen.io/nunllunb-the-reactor">@nunllunb-the-reactor</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>
このJavaScriptコードは、円が左右に動くアニメーションを実現します。

##### CSSでのアニメーション
```css
@keyframes moveCircle {
0% { transform: translateX(0); }
50% { transform: translateX(50px); }
100% { transform: translateX(0); }
}

circle {
animation: moveCircle 2s infinite;
}
```
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="WbeoMqX" data-pen-title="Untitled" data-preview="true" data-user="nunllunb-the-reactor" 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/nunllunb-the-reactor/pen/WbeoMqX">
  Untitled</a> by Saku (<a href="https://codepen.io/nunllunb-the-reactor">@nunllunb-the-reactor</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

このCSSコードも、先のJavaScriptの処理と同様、円が左右に動くアニメーションを実現します。

## まとめ
今回はSVGについて取り上げました。
今までSVGはロゴ画像などの実装やHTMLで少し扱うくらいで、そこまで複雑な利用をしたことがなかったので、改めて私自身も勉強になりました！

JPGやPNGから見るWebpのような次世代形式にあたる存在は、現状SVGにはなく、それだけ代替されてない強みがあるということかな？とも思うので、今後も積極的に活用していきたいです。

---

**特に参考になったサイト**
https://developer.mozilla.org/ja/docs/Web/SVG
https://www.w3.org/Graphics/SVG/WG/wiki/Secret_Origin_of_SVG