こうこく
作 ▸
改 ▸

aタグのdownload属性を使ってCanvasを画像として保存する

右クリックして『名前を付けて画像で保存』でいいんですが。

a タグの download 属性を使うと、HTMLだけでファイルのダウンロードリンクを作れます。

href 属性にはダウンロード対象のファイルURLを、download 属性にはダウンロード時のファイル名を指定します。

JavaScriptでファイルダウンロード処理を実現する - Qiita

これと canvastoDataURL メソッドを組み合わせると、canvas の内容を画像でダウンロードするリンクを作れます。ダウンロードリンクを押したときに canvas の内容を toDataURL でData URIに変換して、href に設定するだけです。

以下にサンプルを置いておきます。

See the Pen Untitled by napoporitataso (@napoporitataso) on CodePen.

HTML
<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8" />
	<meta name="robots" content="noarchive" />
	<title>Canvasダウンロード サンプル</title>
</head>
<body>
	<canvas id="src-canvas"></canvas><br />
	<a id="download-link" href="" download="">画像としてダウンロード</a>
	<script src="script.js"></script>
</body>
</html>
JavaScript
(() => {
  // Canvasの高さ・幅設定 (256px)
  const canvas = document.getElementById('src-canvas');
  canvas.width = canvas.height = 256;
  
  // Canvasを黒で塗りつぶして、白い円を描画
  const ctx = canvas.getContext('2d');
  ctx.fillStyle = 'rgba(0,0,0,1)';
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  ctx.strokeStyle = 'rgba(255,255,255,1)';
  ctx.lineWidth = 2;
  ctx.beginPath();
  ctx.arc(128, 128, 100, 0, Math.PI * 2, false);
  ctx.stroke();
  
  // download属性付きリンククリック時
  document.getElementById('download-link').addEventListener('click', (e) => {
    // data:URLを自身のリンク先として設定すると、このあとダウンロードされる
    const a = e.target;
    a.href = canvas.toDataURL(); // Canvasからdata:URLを取得
    a.download = `${new Date().getTime()}.png`; // ダウンロードファイル名はタイムスタンプ
  });
})();

[2021-03-21 追記] 3/8に上書き保存ができるか否かについてコメントをいただきました。自分の知る範囲内では上書き保存はできないので、同名でダウンロードさせることになり、ダウンロード後のファイル名にはどうしても (1) とかが付きます。いわゆる「名前をつけて保存」ダイアログすらJSからは出す方法が見つからないので、ファイル保存に関してはあんまり自由度高くないみたいです。

この記事に何かあればこちらまで (非公開)