canvasで描画したデータを、Base64エンコードした文字列で取得するメソッドがtoDataURLです。
toDataURL() メソッド – Canvasリファレンス – HTML5.JP
これにより、canvasの画像データをGETやPOSTで送信したり、ブラウザのlocalStrageやsessionStrageに保存して後で利用するなどのことが非常にやりやすくなります。ただし、このメソッドは利用する上でいくつかの注意点があります。
非対応のブラウザがある
canvas対応であっても、一部のメソッドの対応が抜けているケースがいくつかあります。具体的には、Android 2.x の標準ブラウザ等がそれです。また、そもそもcanvasに対応していないIE8以下も、ExplorerCanvasというライブラリで擬似的に対応させたりしている場合、toDataURLは非対応であったりします。
canvasでデータのやり取りをする場合、一部の環境では別のフォロー策を取っておかないとなりません。
なお、Android 2.xであれば、下記のjsライブラリを読み込むことで、非対応のVerでもtoDataURLが使えるようになるようです。(ちなみにAndroid 3以降は問題ないらしいです)
外部サイトの画像をdrawImageすると使えなくなる
セキュリティ対策だと思いますが、drawImageメソッドで画像を貼り付ける時、その読み込んだ画像が外部サイト(クロスドメイン)であったりすると、toDataURLメソッドは画像データを返さなくなります。画像オブジェクトを取り出すgetImageDataメソッドも同様だそうです。画像データを扱う場合は、基本的にスクリプトと同じドメイン(ローカルパスで指定できる範囲)で完結するようにしておくと良いです。
なおiconDecotterは、Twitterアイコンも一旦サーバーに保存して、そこから呼び出してcanvasにdrawImageしているので、この制限を回避しています。
基本はpng形式
引数でMIMEタイプを指定することも出来ますが、指定がない場合はpng形式のデータになります。また、これもブラウザによってjpegが対応していたりいなかったり、bmpが対応していたりいなかったりすることがあるので、pngで扱っておくのが最も安全です。
エラー判定について
上記諸々のケースにおいて、toDataURLが正常に動作しない場合、基本的に返り値は ”data:,“ になります。ですので、スクリプト上ではとりあえずtoDataURLしてみて、 data:, が返って来たら使えないものとして判定する、というロジックが良いのではと思います。
実例など
ex.1 canvasで描画したデータを<img>にコピーする
canvasのデータをtoDataURLメソッドで取り出したあと、それをそのままDOMでimgタグのsrc属性に挿入すると、canvasの描画内容と同じものが画像として表示されます。以下サンプルです。
左がcanvas、右がimgです。動作としては左を右にコピーするだけですが、toDataURLで取得してsrc属性へ、という手順です。また、このデータは保持しておけばcanvasにdrawImageで再描画するということも可能ですので、COOKIEやlocasStrageなどを利用すれば、canvasで編集されたデータをセーブしておいて、次に開いた時にすぐ再開するということも可能です。
ex.2 canvasで描画した画像を送信してサーバーに保存する(PHP)
canvasからtoDataURLで取得したデータを、フォームの<input type=”hidden”>などにDOMで仕込み、任意のサーバーサイドスクリプトに送信してそのデータを保存、といったことが出来ます。絵チャットの投稿などに応用できそうです。送信するまでの部分は省略します。送信した後、受け側のスクリプト例が以下です。
//canvasデータがPOSTで送信されてきた場合 $canvas = $_POST["canvas_data"]; //ヘッダに「data:image/png;base64,」が付いているので、それは外す $canvas = preg_replace("/data:image/png;base64,/i","",$canvas); //残りのデータはbase64エンコードされているので、デコードする $canvas = base64_decode($canvas); //まだ文字列の状態なので、画像リソース化 $image = imagecreatefromstring($canvas); //画像として保存(ディレクトリは任意) imagepng($image ,”./”);
データヘッダの「data:image/png;base64,」の文字列を取り除くことと、データ自体もBase64エンコードされているのでデコードするところがポイントです。pngじゃない場合は適宜形式を変えて下さい。
コメント
[…] 述のようにインターネットアクセスでいいのですけど、 同じドメイン上に存在するファイルという扱いをしなくてはならない事情があるので、 そういう手法を取ってます。 (CORSの指定 […]
[…] canvasド素人の自分でも、ちょっと頑張れば使えてしまうレベルです。 canvas.toDataURLメソッドを使う canvasの画像データをダウンロードする方法。 […]