[Javascript] Canvasを使って大きい画像の縮小データをbase64で出力までをブラウザのみで行う方法

2017年3月23日

Javascript テクノロジー プログラミング

WEBサービス構築の際に特定の画像をブラウザ内に保持しておきたい事があります。 ユーザーアイコンや、任意の指定画像など、数Kb程度の画像であれば、base64形式にしてlocalStorageに保存しておくと便利です。 ただ、スマホでこうした作業を行う場合、サーバーに画像を送ってimageMagicで画像をリサイズしてブラウザでリクエストし直すという事が想像できますが、HTML5はこうした作業がブラウザ内の機能でできてしまいます。 そのやり方とサンプルソースコードを書いておきます。

Summery

  1. ”input type=file”でローカルPCやスマホに保存されている画像を読み込む。
  2. この段階でローカルファイルをブラウザに読み込む事ができます。
  3. 読み込んだ画像をcanvasに読み込み、特定サイズに縮小して表示。
  4. 縮小されて表示した画像をbase64形式として文字列で取得
  5. base64データをlocalStorageに保存する。
その後localStorageが読み込みできるページであれば、画像をURLで表示するのではなく、 キャッシュから表示できるので、超高速に表示できる&ネットを介さないので、帯域の節約になる。 base64データはIMGタグのsrc属性にそのまま入れ込めば、ブラウザでは画像として表示されるので、扱いは楽だと思いますよ。

ソースコード

<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"/> <title>image2base64</title> </head> <body> <h1>Web Page Stickies options</h1> <canvas id="imgViewCanvas" style="border:1px solid #CCC;"></canvas> <input type="file" name="file" id="file"> <script src="img2base64.js"></script> </body> </html> ;(function(){ var fileElm = document.getElementById("file"); fileElm.onchange = function(event){ var w=h=128; var canvas = document.getElementById("imgViewCanvas"); canvas.width = w; canvas.height = h; var fileReader = new FileReader(); fileReader.onload = function(){ var ctx = canvas.getContext("2d"); var ctxImg = new Image(); ctxImg.onload = function(){ //横長 if(this.width > this.height){ var margin = Math.floor((this.width - this.height) /2); ctx.drawImage(this ,margin,0, this.height , this.height , 0,0,w,h); } //縦長 else if(this.width < this.height){ var margin = Math.floor((this.height - this.width) /2); ctx.drawImage(this ,0,margin, this.width , this.width , 0,0,w,h); } //正方形 else{ ctx.drawImage(this ,0,0, this.width , this.height , 0,0,w,h); } var base64 = canvas.toDataURL(); console.log(base64); window.localStorage.setItem("hoge" , base64); }; ctxImg.src = this.result; canvas.style.setProperty("display","block",""); }; fileReader.readAsDataURL(event.target.files[0]); }; })();

実行画像

解説

canvasタグの取得

var canvas = document.getElementById("imgViewCanvas"); canvas.width = 100; canvas.height = 100; もし、canvasタグがない場合は、createしてください。 var canvas = document.createElement("canvas"); canvas.width = 100; canvas.height = 100; document.body.appendChild(canvas); widthとheightを指定しているのは、これがないとcanvasはpixel値が設定されないようです。 cssのwidthとheightを記述しても、canvasの値は個別に保持していて、それぞれの値が違う場合、画像が等倍にならないようです。 ハマりポイントなので、要注意を!!

canvasのcontextの取得

var ctx = canvas.getContext("2d"); ここまではお決まりの工程なので、毎回コピペでも良いぐらいです。

読み込んだ画像のセット

var ctxImg = new Image(); ctxImg.onload = function(){...}; ctxImg.src = this.result; srcをセットすると、画像を読み込むのでonloadで読み込みタイミングをみはからって、読み込み後に各種処理を行います。

読み込んだ画像を正方形にする

//横長 if(this.width > this.height){ var margin = Math.floor((this.width - this.height) /2); ctx.drawImage(this ,margin,0, this.height , this.height , 0,0,w,h); } //縦長 else if(this.width < this.height){ var margin = Math.floor((this.height - this.width) /2); ctx.drawImage(this ,0,margin, this.width , this.width , 0,0,w,h); } //正方形 else{ ctx.drawImage(this ,0,0, this.width , this.height , 0,0,w,h); } ここの工程は、正方形に拘らなければ、もっと簡素に書いてください。

canvasのレンダリング情報をbase64で取得する

var base64 = canvas.toDataURL(); 何の迷いもなく、base64が取得できます。 そのままsrcに入れると画像として利用できるのもポイントです。

ローカルストレージにキャッシュする

window.localStorage.setItem("hoge" , base64); base64自体が文字列なので、そのままキャッシュデータに保存できます。 もしかするとエンコードが必要かもしれませんが、僕の環境(chrome)では、問題なく動いてます。 細かな画像がキャッシュして帯域もエコに利用するようにしましょう。

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。