Chromeでsvg faviconが利用可能になったがアニメーションは動かない

# tl;dr

- chromeのfaviconはsecure static mode

# 概要

[こちら](https://www.webcreatorbox.com/tech/svg-favicon
)の記事を読んで、Google Chrome 80以降でfaviconにsvgが使えるようになったことを知りました。

svgといえばベクタ画像なので拡大縮小しても画像が劣化しないというのが大きな特徴ですが、個人的にはアニメーションを記述できる点も楽しいのでsvgのfaviconでanimationが動くかどうか確認しました。実際に使う機会は無さそうですが。

# 方式

svgをanimationさせる方法は、svg自身に記述するもので3種類あります。
https://ics.media/entry/15970/

1. css animation
2. SMIL
3. javascript


## index.html

次のhtmlファイルからfavicon.svgを読み込みます。
bodyでも読み込んでいるのは、favicon特有の問題かどうかを区別するためです。

```html:index.html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>favicon test</title>
  <link rel="icon" href="/favicon.svg">
</head>

<body>
  <img src="/favicon.svg" width="200px" />
</body>
</html>
```

## CSS animation

```xml:favicon.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
  <polygon class="square" points="40,40 40,160 160,160 160,40" style="fill:yellow;" />
  <style>
  .square {
    animation: rotation 3s linear infinite;
    transform-origin: center;
  }
  @keyframes rotation {
    from {
      transform: rotate(0deg);
    }
    to {
      transform: rotate(360deg);
      }
  }
  </style>
</svg>
```

## SMIL

```xml:favicon.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
  <polygon class="square" points="40,40 40,160 160,160 160,40" style="fill:yellow;">
    <animateTransform type="rotate" attributeName="transform" attributeType="XML" values="0 100,100;360 100,100" dur="3s" repeatCount="indefinite" />
  </polygon>
</svg>
```

## javascript

```xml:favicon.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
  <polygon id="square" points="40,40 40,160 160,160 160,40" style="fill:yellow; transform-origin: center;" />
  <script type="text/javascript">
    let time = 0;
    const square = document.querySelector('#square');
    function animate() {
        requestAnimationFrame(() => {
            const deg = 2 * time // 360;
            square.style.transform = `rotate(${deg}deg)`;
            time += 1;
            animate();
        });
    }
    animate();
  </script>
</svg>
```

imgタグで読みこむsvgはsecure animated modeとなるので、javascriptが効きません。

> An SVG embedded within an ‘image’ element must be processed in secure animated mode
> (snip)
> The same processing modes are expected to be used for other cases where SVG is used in place of a raster image, such as an HTML ‘img’ element or in any CSS property that takes an <image> data type. 
https://svgwg.org/svg2-draft/conform.html#referencing-modes

[こちらを参考に](https://qiita.com/imk2o/items/f60c9fe9c55cb48a8e8a)html側はobjectで埋め込むよう変更します。

```html:index.html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>favicon test</title>
  <link rel="icon" href="/favicon.svg">
</head>

<body>
  <object data="/favicon.svg" width="200px" type="image/svg+xml"></object>
</body>
</html>
```

## その他

[こちらの記事](https://ics.media/entry/15970/)では4番目の方法としてAfterEffectなどのソフトを利用する方法が紹介されていますが、最終的にはjavascriptで動かすようです。
またfaviconをanimationさせる方法は他に外からjavascriptでfavicon画像そのものを差し替える方法がありますが、こちらは省略。

# 環境

MacOSのChromeとFirefoxで表示してみます。

```console
$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.15.3
BuildVersion:   19D76
```
Google Chrome バージョン: 80.0.3987.106（Official Build） （64 ビット）
Firefox 69.0.1 (64-bit)

# 結果

## Firefox & CSS

bodyもfaviconも回っています。

![firefox_css.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266939/c5046611-cc1f-316b-7d03-9ec81c6aac4c.gif)

## Firefox & SMIL

bodyもfaviconも回っています。

![firefox_smil.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266939/380da0d1-4ba8-7469-3e37-0c2c159a9f71.gif)


## Firefox & javascript

bodyは回っていますがfaviconは回っていません。

![firefox_javascript.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266939/ac624b56-1122-244a-8ec8-de040c06efa7.gif)


## Chrome & CSS

bodyは回っていますがfaviconは回っていません。

![chrome_css.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266939/464d09dd-47c5-808b-9a61-77609b804047.gif)


## Chrome & SMIL

bodyは回っていますがfaviconは回っていません。

![chrome_smil.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266939/0a9c44ed-4e4c-1eb7-8e99-c5375f430287.gif)


## Chrome & javascript

bodyは回っていますがfaviconは回っていません。

![chrome_javascript.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266939/5cc80734-a1f4-cd0d-1c42-f96d32d57c6a.gif)


# 結果まとめ

|          | Google Chrome | Firefox |
|----------|---------------|---------|
|CSS       | x             | o       |
|SMIL      | x             | o       |
|javascript| x             | x       |

faviconをanimationさせようとした結果表のようになりました。

それぞれのブラウザのsvg faviconのモードは次のように推測されます。

- Firefoxは`declarative animation`が可能で`script execution`が不可能なので[Animated mode](https://svgwg.org/svg2-draft/conform.html#animated-mode)または[Secure Animated mode](https://svgwg.org/svg2-draft/conform.html#secure-animated-mode)
- Chromeは`declarative animation`も`script execution`も不可能なので[ここ](https://www.chromestatus.com/feature/5180316371124224)に書いてある通り[secure static mode](https://svgwg.org/svg2-draft/conform.html#secure-static-mode)

Chromeについては`declarative animation`が不可能である一方次の記述があるためSMILアニメーションは動くと思ったのですが動きませんでした。読み間違いでしょうか…?

> Chrome serves the SVG in secure static mode, but does apply SMIL animations using the document start time (0).


# まとめ

- Chrome 80以降でfaviconにsvg形式利用可能になりましたがアニメーションはできません。残念。
- Firefoxでは以前からfaviconにsvgが利用可能で、アニメーションも動きます。
- ChromeでSMILアニメーションが動かない点が公式情報と異なるので、何か誤りがあれば教えて下さい。

# 参考

https://caniuse.com/#search=svg%20favicon
https://www.chromestatus.com/feature/5180316371124224
https://ics.media/entry/15970/
https://animated-svg-favicon.glitch.me/