Reactでhtml2canvasを使って要素を画像としてダウンロードする方法

## はじめに
https://qiita.com/Sicut_study/items/ccfc451360d3f22bde63

この課題に取り組む中でダウンロードの実装を行いました。
「特定の要素を画像としてダウンロードする」と言葉で聞くとすごい大変な処理をしないといけないのではないかと思ってしまいますが、html2canvasを使うことで簡単に実装できました。
今回はそのhtml2canvasの使い方について書いていきます。


## html2canvasを使うと何ができるのか
html2canvasは、指定したHTML要素をキャンバスに描画し、その描画結果を画像として保存できるJavaScriptライブラリです。これにより、ウェブページ上の任意の要素を画像としてキャプチャし、ダウンロードすることが可能になります。

## 実装準備
html2canvasをプロジェクトにインストールします。

```bash:bash
npm install html2canvas
```

## サンプルコード

```react:APP.tsx
import React from 'react';
import html2canvas from 'html2canvas';

function App() {
  // 画像化とダウンロードをトリガーする関数
  const onClickExport = (): void => {
    // 画像化したい要素を取得
    const target = document.getElementById("target-component") as HTMLElement;
    // html2canvasを使って要素をキャンバスに描画
    html2canvas(target).then((canvas: HTMLCanvasElement) => {
      // キャンバスをPNG形式のデータURLに変換
      const targetImgUri = canvas.toDataURL("image/png");
      // 画像をダウンロード
      saveAsImage(targetImgUri);
    });
  };

  // 画像をダウンロードする関数
  const saveAsImage = (uri: string): void => {
    // ダウンロードリンクを作成
    const downloadLink = document.createElement("a");
    if (typeof downloadLink.download === "string") {
      downloadLink.href = uri;
      downloadLink.download = "component.png"; // ダウンロードするファイル名を指定
      document.body.appendChild(downloadLink);
      downloadLink.click(); // 自動的にクリックしてダウンロードを開始
      document.body.removeChild(downloadLink);
    } else {
      window.open(uri); // ダウンロードリンクが使えない場合は新しいタブで開く
    }
  };

  return (
    <div style={styles.container}>
      {/* 画像化するターゲット要素 */}
      <div id='target-component' style={styles.target}>
        <h1>ここが画像としてダウンロードされるよ！</h1>
      </div>
      {/* 画像化を実行するボタン */}
      <button onClick={onClickExport} style={styles.button}>PNG出力</button>
    </div>
  );
}

// CSSスタイル
const styles = {
  container: {
    display: 'flex', 
    flexDirection: 'column' as 'column', 
    justifyContent: 'center', 
    alignItems: 'center', 
    height: '100vh', 
  },
  target: {
    marginBottom: '20px', 
  },
  button: {
    padding: '10px 20px', 
    fontSize: '16px', 
  },
};

export default App;

```
## コードの説明
**画像化とダウンロードの処理**

onClickExport関数: ボタンがクリックされたときに実行され、html2canvasを使用して指定した要素をキャンバスに描画します。描画されたキャンバスはPNG形式のデータがURLに変換され、saveAsImage関数を呼び出して画像をダウンロードします。

```react
const onClickExport = (): void => {
  const target = document.getElementById("target-component") as HTMLElement;
  html2canvas(target).then((canvas: HTMLCanvasElement) => {
    const targetImgUri = canvas.toDataURL("image/png");
    saveAsImage(targetImgUri);
  });
};
```

- document.getElementById("target-component")で画像化したい要素を取得
- html2canvas(target)を呼び出し、指定した要素をキャンバスに描画
- canvas.toDataURL("image/png")でキャンバスをPNG形式のデータURLに変換

<br>

**画像の保存処理**

saveAsImage関数: 生成された画像をダウンロードするためのリンクを作成し、自動的にクリックしてダウンロードを開始します。リンクがサポートされていない場合は、新しいタブで画像を開きます。

```react
const saveAsImage = (uri: string): void => {
  const downloadLink = document.createElement("a");
  if (typeof downloadLink.download === "string") {
    downloadLink.href = uri;
    downloadLink.download = "component.png";
    document.body.appendChild(downloadLink);
    downloadLink.click();
    document.body.removeChild(downloadLink);
  } else {
    window.open(uri);
  }
};
```

- document.createElement("a")でダウンロードリンクを作成
- downloadLink.href = uriでリンク先を設定しdownloadLink.downloadでファイル名を指定
- downloadLink.click()でリンクをクリックし、画像をダウンロード

## 完成図

![ダウンロード処理実装.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2120218/08c91439-9273-b37a-014a-c6a5913100fe.gif)

## まとめ
今回はhtml2canvasの実装方法について紹介しました。
検索すれば実装方法も応用的な使い方など出てくるのでぜひ一度実装してみてください。
この記事が少しでも参考になれば幸いです。