LoginSignup
17
26

More than 5 years have passed since last update.

canvasの図形を画像として出力する時のブラウザ毎の処理

Posted at

canvasに描かれた図形を画像として出力する方法としてデータURIスキームの方法もありますがBlobを使用した出力方法もあるので、それぞれのブラウザ毎に出力を分けてローカルに保存できるようにしてみます。

canvasの図形を画像出力する

既に何か描かれているcanvas要素から画像を出力するコードです。

var
  // canvas要素
  canvas = document.querySelector('#canvas'),

  // 出力した画像を表示するimg要素
  image = document.querySelector('#outputImg'),

  // 画像のダウンロードリンク
  link = document.querySelector('#downloadLink'),

  blob, imageURL;

// リンクにdownload属性を設定
link.download = 'canvas.png';

if (canvas.toBlob) {
  // HTMLCanvasElement.toBlob() が使用できる場合

  // canvasの図形をPNG形式のBlobオブジェクトに変換
  canvas.toBlob(function (blob) {
    // BlobオブジェクトにアクセスできるURLを生成
    imageURL = URL.createObjectURL(blob);

    // 要素にURLを適用
    image.src = imageURL;
    link.href = imageURL;
  });

} else if (canvas.msToBlob) {
  // IE10以降やEDGEで使えるメソッド

  // canvasの図形からPNG形式のBlobオブジェクトを取得
  blob = canvas.msToBlob();

  // BlobオブジェクトにアクセスできるURLを生成
  imageURL = URL.createObjectURL(blob);

  // 要素にURLを適用
  image.src = imageURL;
  link.href = imageURL;

  // IEとEDGEの場合 navigator.msSaveBlob() でBlobオブジェクトを保存できるメソッドがある
  link.addEventListener('click', function (ev) {
    ev.preventDefault();
    navigator.msSaveBlob(blob, 'canvas.png');
  });

} else {
  // Blobオブジェクトに変換できない場合はPNG形式のデータURIスキームとして出力
  imageURL = canvas.toDataURL();

  // 要素にURLを適用
  image.src = imageURL;
  link.href = imageURL;
}

Blobオブジェクト用のURLは blob:https://example.com/12345678-1234-5678-9012-123456789012blob:12345678-1234-5678-9012-123456789012 といったような特殊なものになっています。
実際にサーバーにこのファイルがあるわけではなく、ブラウザ内部で持っているバイナリデータにアクセスするためのURLみたいなものですね。
このURLは URL.revokeObjectURL(blobURL) を使用したり、他のページへ遷移した時に破棄されます。

HTMLCanvasElement.toBlob() が非同期処理なのに対し、IE・EDGE独自実装の HTMLCanvasElement.msToBlob() は非同期処理ではないので大きな図形を扱う場合 msToBlob() では変換が終わるまで他のコードが実行できない事になります。

HTMLCanvasElement.toBlob() - Web API インターフェイス | MDN

MDNに HTMLCanvasElement.toBlob() のポリフィルもありますが、あくまでこういう処理でできるよ程度のものなので、パフォーマンスを考えると実用的ではありません。

Blobオブジェクトのメリット

Blobオブジェクトであれば blob.size のように出力後のファイルサイズを取得することができます。
他にもimg要素に出力する時、データURIスキームだと画像のデータがテキストデータとして存在することになるので大き目の画像の場合ブラウザ側の動作が重くなる可能性がありますが、Blobオブジェクトの場合はブラウザ内部にバイナリデータとして持っているので動作は軽いです。

Blob - Web API インターフェイス | MDN

17
26
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
26