スクリーンショット機能を実装することになったのでライブラリを調べてみた

開発中のプロジェクトでスクリーンショットを撮る機能を実装することになりました。ブラウザの機能でやってく(ry...と思いましたが。スクリーンショットを自力で実装するとコスト高そうなのでスクリーンショットが撮れるライブラリを探したときのメモです。

## html2canvas

スクリーンショットを撮るときにはよく使われているライブラリのようで、検索すると結構記事が出てきます。この記事の執筆時点で29.7kスターがついており、npmのサイトで確認すると1週間で100万以上ダウンロードされていました。 [公式ドキュメント](https://html2canvas.hertzen.com/documentation)にも記載がありますが注意点として100％正確ではない可能性があったり、同一オリジンではないと画像が読み込めなかったりするようです。

まずはライブラリをインストールします。
```shell
npm i html2canvas
```

つづいてスクリーンショットを撮るためにボタンを設置します。
```html:index.html
<body>
  <button data-screenshot>スクリーンショットを撮る</button>

  ...以下コンテンツ...
</body>
```

ボタンを押したときに撮影するためのスクリプトを書きます。

```ts:index.ts
import html2canvas from 'html2canvas';

const screenShotButton = document.querySelector<HTMLButtonElement>('[data-screenshot]');

screenShotButton?.addEventListener('click', () => {
  // ファイル名に時間を入れるため
  const formatDate = () => {
    const date = new Date();
    const year = date.getFullYear();
    const month = (date.getMonth() + 1).toString().padStart(2, '0');
    const day = date.getDate().toString().padStart(2, '0');
    const hours = date.getHours().toString().padStart(2, '0');
    const minutes = date.getMinutes().toString().padStart(2, '0');
    const result = `${year}${month}${day}T${hours}${minutes}`;
    return result;
  };

  const option = {
    useCORS: true,
  };

  html2canvas(document.body, option)
    .then((canvas) => {
      const dataUrl = canvas.toDataURL('image/jpeg');
      const link = document.createElement('a');
      link.download = `screenshot-${formatDate()}.jpg`;
      link.href = dataUrl;
      link.click();
    })
    .catch((error) => {
      console.log(error);
    });
}, false);
```

これで設置したボタンを押下するとスクリーンショットを撮ることができます。簡単ですね。参画中のプロジェクトでは外部のリソースを使用しているところがあるため、[オプション](https://html2canvas.hertzen.com/configuration)として`useCORS: true`を渡しています。これつけないと画像表示されませんでした。これで外部リソースも表示され、スクリーンショットを撮ることまでできましたが、SVGだけ写りませんでした。検索するとSVGがうまく表示されないことがあるようで、事前にSVGからjpegやpngへ変換が必要そうでしたのでhtml2canvasを使うのは諦めました。

## modern-screenshot
先ほどのhtml2canvasを諦めてたどり着いたのがこちらのライブラリです。モダンですって。スター、ダウンロードはそんなに多くありませんがモダンという言葉に惹かれて使ってみました。使い方はhtml2canvasとあまり変わらないです。

一応インストールから。
```shell
npm i modern-screenshot
```

一応設置も。
```html:index.html
<body>
  <button data-screenshot>スクリーンショットを撮る</button>

  ...以下コンテンツ...
</body>
```

スクリプトもほぼ変わらず`method(node: Node, options?: Options)`という形式です。違いは保存する形式でインポートする関数が変わるようです。
また渡せる[オプション](https://github.com/qq15725/modern-screenshot/blob/HEAD/src/options.ts)はここから見ろってなっています。
```ts:index.ts
import { domToJpeg } from 'modern-screenshot';

const screenShotButton = document.querySelector<HTMLButtonElement>('[data-screenshot]');

screenShotButton?.addEventListener('click', () => {
  const formatDate = () => {
    const date = new Date();
    const year = date.getFullYear();
    const month = (date.getMonth() + 1).toString().padStart(2, '0');
    const day = date.getDate().toString().padStart(2, '0');
    const hours = date.getHours().toString().padStart(2, '0');
    const minutes = date.getMinutes().toString().padStart(2, '0');
    const result = `${year}${month}${day}T${hours}${minutes}`;
    return result;
  };
  
  domToJpeg(document.body)
    .then((dataUrl) => {
      const link = document.createElement('a');
      link.download = `screenshot-${formatDate()}.jpg`;
      link.href = dataUrl;
      link.click();
    })
    .catch((error) => {
      console.log(error);
    });
}, false);
```

こちらのライブラリはsvgも保存できていました！
ということで今回のプロジェクトではこちらを採用することにしました。しかし今後どこか写っていないところがあるかもしれません。そうなると他ライブラリをあたるか、自力実装するか。自力実装はｲﾔﾀﾞ、自力実装はｲﾔﾀﾞ...。
というかブラウザの機能でや(ry。