リロードするたびランダムに変わるfaviconを作った

## これは何

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/b865c724-bf95-aa70-0b7e-044932b17d4f.gif)

- リロードするたびにfaviconが変わる仕組みを作ってみました
    - 英数字からランダムで1文字表示されるようにしていますが、日本語や絵文字でも実現可能です
- なんとなくで作ったので完全にネタです！

## リポジトリ

https://github.com/xrxoxcxox/qiita-dynamic-favicon

- 大したコードは書いていませんがリポジトリを公開します
- 馴染みがあるのでReactで作っただけで、特に意図はありません


## 実際に作った手順

### 下準備

まずはCreate React App。

```shell
npx create-react-app qiita-dynamic-favicon
```

そしてReact Helmetのインストール。

```shell
yarn add react-helmet
```

アプリケーションを起動します。

```shell
yarn start
```

現段階でのfaviconはこれ。
いつも見るやつですね。

![デフォルトのfavicon](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/f8d116a6-7da8-1777-85b1-90306b58253e.png)

### 文字をfaviconにする

前置きが長くなってしまいましたがここからが本番です。
まずは`public/index.html`で指定されているfaviconを消します

```diff_html:public/index.html
  <head>
    <meta charset="utf-8" />
-   <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <title>React App</title>
  </head>
```

そして`src/App.js`を編集します。

```diff_jsx:src/App.js
  import logo from './logo.svg';
  import './App.css';
+ import { Helmet } from "react-helmet";

  function App() {
    return (
      <div className="App">
+       <Helmet>
+         <link
+           rel="icon"
+           href={`
+             data:image/svg+xml;
+             utf8,
+             <svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+               <text font-size="16" x="50%" y="50%" dominant-baseline="middle" text-anchor="middle">
+                 a
+               </text>
+             </svg>
+           `}
+         />
+       </Helmet>
        <header className="App-header">
        {/* 以下省略 */}
```

Base64でsvgを埋め込むことで、faviconの中で生きたテキストを扱えるようになりました。
ただし現時点では`a`しか表示されません。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/ded71606-fe87-7cac-aa64-c8aeeefcc423.gif)

### 表示文字列をランダムにする

`a`と直接文字を書いているので、ランダムな1文字を選んで挿入してあげればOK。
`string`で文字列を定義しているだけなので、日本語でも絵文字でも可能です。

```diff_jsx:src/App.js
  function App() {
+   const string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
+   const random = string[Math.floor(Math.random()*string.length)]
    return (
      <div className="App">
        <Helmet>
          <link
            rel="icon"
            href={`
              data:image/svg+xml;
              utf8,
              <svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
                <text font-size="16" x="50%" y="50%" dominant-baseline="middle" text-anchor="middle">
-                 a
+                 ${random}
                </text>
              </svg>
            `}
          />
        </Helmet>
        <header className="App-header">
        {/* 以下省略 */}
```

ランダムに英数字を挿入する部分のコードは以下の記事を参考にしました。

https://qiita.com/fukasawah/items/db7f0405564bdc37820e

### font-familyを変える

現段階だとfont-familyはマシン依存。
私の環境の場合はヒラギノ角ゴシックが表示されているようです。
（目視で利きフォントしているだけで、サイズも小さいので若干怪しいですが……。）

せっかくなのでWebフォントを使ってデコラティブにしてみましょう。
Google Fontsでハンドライティング系のフォントを見繕ってきました。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/d4aa2822-6f57-7ebd-7851-1797a35b8469.png)

https://fonts.google.com/specimen/Dancing+Script

```diff_jsx:src/App.js
  return (
    <div className="App">
      <Helmet>
+       <link rel="preconnect" href="https://fonts.googleapis.com" />
+       <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
+       <link href="https://fonts.googleapis.com/css2?family=Dancing+Script&display=swap" rel="stylesheet" />
        <link
          rel="icon"
          href={`
            data:image/svg+xml;
            utf8,
            <svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-             <text font-size="16" x="50%" y="50%" dominant-baseline="middle" text-anchor="middle">
+             <text font-family="'Dancing Script', cursive" font-size="16" x="50%" y="50%" dominant-baseline="middle" text-anchor="middle">
                ${random}
              </text>
            </svg>
          `}
        />
      </Helmet>
```

こんな場所からfont-familyを変更できるのは今回始めて知りました。
何の役に立つかは分かりませんが、遊んでみるものですね。

以上で完成です。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/b865c724-bf95-aa70-0b7e-044932b17d4f.gif)