SVGのアニメーション実装：animate要素の使い方

## はじめに

SVG（Scalable Vector Graphics）は、ベクター画像を描画するためのXMLベースのフォーマットです。SVGには、アニメーションを実装するための強力な機能が組み込まれており、特にSMIL（Synchronized Multimedia Integration Language）を使用する方法が一般的です。本記事では、animate要素を中心に、SVGアニメーションの基本的な使い方を解説します。JavaScriptやCSSを使用せずに、ネイティブなSVG機能だけでシンプルかつ効率的なアニメーションを実現する方法を学びましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/59081990-8a29-a47c-d6a6-79afc115afd5.png)


## 1. animate要素の基本

animate要素を使用すると、SVG要素の属性値を時間とともに変化させることができます。これにより、動的なビジュアル表現が可能になります。

### 1.1 単純な値の変化（数値）

以下の例では、円の半径が20から40に変化します。

```xml
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
    <circle 
        cx="50" 
        cy="50" 
        r="20" 
        fill="blue">
        <animate 
            attributeName="r"
            from="20"
            to="40"
            dur="2s"
            repeatCount="indefinite"
        />
    </circle>
</svg>
```

**解説:**
- `<circle>`要素の半径`r`を20から40に2秒間かけて変化させ、無限に繰り返します。
- attributeName="r": 変化させる属性
- from="20": 開始値
- to="40": 終了値
- dur="2s": アニメーション時間
- repeatCount="indefinite": 繰り返し回数

![animation01.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/c5598fce-39d6-1d85-2180-318022dffb69.gif)

### 1.2 複数の値を順番に変化

以下の例では、円の半径が20から40、次に30、再び20に変化します。

```xml
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
    <circle 
        cx="50" 
        cy="50" 
        r="20" 
        fill="blue">
        <animate 
            attributeName="r"
            values="20;40;30;20"
            dur="4s"
            repeatCount="indefinite"
        />
    </circle>
</svg>
```

**解説:**
- `values`属性を使用して、半径`r`を20から40、30、再び20に順番に変化させます。全体のアニメーション時間は4秒です。
- values属性ではセミコロンで区切って複数の値を指定できます

![animation02.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/9f45d5d2-8600-689f-ab78-b08b5aeefa35.gif)


## 2. アニメーションの種類と使い分け

SVGでは、さまざまなアニメーションを実装するための要素が用意されています。ここでは、animateとanimateTransformの使い分けについて解説します。

### 2.1 値のアニメーション（animate）

animate要素を使用して、SVG要素の属性値をアニメーションさせる方法です。色やサイズ、不透明度など、さまざまな属性を対象にできます。

以下の例では、矩形の色と幅が変化します。

```xml
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
    <rect 
        x="20" 
        y="20" 
        width="60" 
        height="60" 
        fill="blue">
        <animate
            attributeName="fill"
            values="blue;red;green;blue"
            dur="4s"
            repeatCount="indefinite"
        />
        <animate
            attributeName="width"
            values="60;30;60"
            dur="2s"
            repeatCount="indefinite"
        />
    </rect>
</svg>
```

**解説:**
- 矩形の`fill`属性を`blue`から`red`、`green`、再び`blue`に4秒間かけて変化させます。
- 同時に、`width`属性を60から30、再び60に2秒間かけて変化させます。

![animation03.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/0e217202-50e2-8166-cffc-b92cab6fb557.gif)


### 2.2 変形のアニメーション（animateTransform）

animateTransform要素を使用して、SVG要素の変形（回転、拡大縮小、移動など）をアニメーションさせる方法です。

以下の例では、矩形が中心を軸に回転します。

```xml
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
    <rect 
        x="20" 
        y="20" 
        width="60" 
        height="60" 
        fill="blue">
        <animateTransform
            attributeName="transform"
            type="rotate"
            from="0 50 50"
            to="360 50 50"
            dur="2s"
            repeatCount="indefinite"
        />
    </rect>
</svg>
```

**解説:**
- 矩形を中心点(50, 50)を軸に0度から360度まで2秒間で回転させ、無限に繰り返します。
- from="0 50 50": 開始角度と回転中心点のx,y座標
- to="360 50 50": 終了角度と回転中心点のx,y座標

![animation04.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/a89a5b4a-9271-e1ae-4052-69d80b513cc9.gif)


## 3. animate要素の主な属性

animate要素には、アニメーションを制御するためのさまざまな属性があります。以下に主要な属性を紹介します。

### attributeName
アニメーションする属性を指定します。
- 数値属性: x, y, width, height, r など
- 色属性: fill, stroke
- 不透明度: fill-opacity, stroke-opacity
- パス: d

### from, to, values
値の変化を指定する方法：
- from-toパターン: 開始値と終了値を指定します。
- valuesパターン: 複数の値をセミコロンで区切って指定します。

### dur
アニメーションの時間を指定します。
- "2s" - 2秒
- "500ms" - 500ミリ秒

### repeatCount
繰り返し回数を指定します。
- 数値 - 指定回数繰り返します。
- "indefinite" - 無限に繰り返します。

### fill
アニメーション終了後の状態を指定します。
- "remove"（デフォルト） - 開始状態に戻ります。
- "freeze" - 終了状態を維持します。

## 4. パスに沿った移動（animateMotion）

animateMotion要素を使用すると、SVG要素を指定したパスに沿って移動させることができます。以下の例では、円がベジェ曲線を描きながら移動します。

```xml
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
    <circle r="5" fill="red">
        <animateMotion
            path="M10,50 C10,10 90,10 90,50 C90,90 10,90 10,50"
            dur="3s"
            repeatCount="indefinite"
        />
    </circle>
</svg>
```

**解説:**
- 赤い円が、指定されたパス`M10,50 C10,10 90,10 90,50 C90,90 10,90 10,50`に沿って3秒間で移動し、無限に繰り返します。
- path属性でベジェ曲線を指定して移動パスを定義しています


![animation05.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/5444edc7-b4b0-67f9-313e-c74807f9d6a6.gif)


## 5. 実践的な例：複数のアニメーションの組み合わせ

複数のアニメーションを組み合わせることで、より複雑で魅力的なビジュアル表現が可能になります。以下の例では、ストロークが回転するローディングサークルを実装しています。

```xml
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
    <circle
        cx="50"
        cy="50"
        r="45"
        fill="none"
        stroke="blue"
        stroke-width="2"
        stroke-dasharray="70.85"
    >
        <animate
            attributeName="stroke-dashoffset"
            values="70.85;0"
            dur="1s"
            repeatCount="indefinite"
        />
        <animateTransform
            attributeName="transform"
            type="rotate"
            values="0 50 50;360 50 50"
            dur="2s"
            repeatCount="indefinite"
        />
    </circle>
</svg>
```

**解説:**
- 青い円のストロークにダッシュパターンを適用し、`stroke-dashoffset`をアニメーションさせることでストロークが描かれるように見せます。
- stroke-dasharray="70.85"は円周の約1/4（2πr/4）を指定しています
- 同時に、`animateTransform`を使用して円全体を中心点(50, 50)を軸に回転させ、ローディングサークルのような効果を実現しています。

![animation06.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/bd8a43a6-ec07-c3a1-e504-5443fe6cfc65.gif)


## まとめ

SVGのanimate要素および関連するアニメーション要素を使用することで、JavaScriptやCSSを使わずにシンプルかつ効率的なアニメーションを実装できます。基本的な属性の変更から複雑な変形やパスに沿った移動まで、さまざまな表現が可能です。この記事を参考に、ぜひ自分のプロジェクトでSVGアニメーションを活用してみてください。