こんにちは。
とある開発で、Canvas要素内の画像をボタン押下でダウンロードしたい場面がありました。
そのような実装は未経験だったので実装する上で学んだ内容を備忘録代わりに記載いたします。
記載したコード
// Canvas要素に画像を描写するためのuseRef
// 画像をCanvas要素に描写する処理は今回は省略
const canvasRef = useRef(null);
const downloadImage = () => {
const canvas = document.querySelector("canvas");
const dataURL = canvas.toDataURL();
const createdLink = document.createElement("a");
createdLink.href = dataURL;
createdLink.download = "download.png";
createdLink.click();
};
return (
<>
<canvas ref={canvasRef}></canvas>
<button onClick={downloadImage}>
画像をダウンロード
</button>
</>
);
実装の流れ
- 前提として、Canvas要素に描画されている画像は
FileReader()を用いてファイルのdata URLが格納されている
※ data URLの例(xx...以下には文字列が続きます)
"data:image/jpeg;base64,xxxxxxxxxxxxx............
- ダウンロードをする際は、上記のdata URLを参照してダウンロード元のURLとする
- buttonタグ自体にはダウンロード機能を持たないため、aタグが持つdownload属性の機能を使って擬似的にダウンロードボタンとする
実装したコードの中身
①Canvas要素内の画像のdata URLを取得する
const canvas = document.querySelector("canvas") as HTMLCanvasElement;
const dataURL = canvas.toDataURL();
Canvas要素の中身を取得した後、toDataURL()を用いてCanvas要素に登録されたdata URLを取得します。
HTMLCanvasElement.toDataURL() メソッドは、 type 引数で指定された形式で画像を表現したものが入った data URL を返します。
なお、toDataURL()は引数で画像形式や画像品質も設定できます。(空欄の場合はpngで出力されます)
例えば画像をjpegで取得したい場合はtoDataURL("image/jpeg")と記述します。
②ダウンロード可能なaタグのDOMを生成する
ファイルをダウンロードするためのHTMLの最小構成は以下のような形です。
<a href="(ファイルのURL)" download="(ファイル名)">
このHTMLと同じ構成のDOMを生成できればいいので、以下のような実装をしました。
const createdLink = document.createElement("a");
createdLink.href = dataURL;
createdLink.download = "download.png";
③ボタンのクリックイベントを生成したaタグのクリックに置き換える
②で生成したボタンのDOM要素をclick()で擬似的にクリックさせます。
const createdLink = document.createElement("a");
createdLink.href = dataURL;
createdLink.download = "download.png";
createdLink.click();
こうすることで関数内の処理でボタンをダウンロードするためのaタグが押下された扱いとなり、画像のダウンロードが実現できます。
最後に
data URLを使った画像データの取得、download属性については今後の開発でも有効活用していきたいです。
参考資料