Canvasの画像をリサイズする簡単な方法【HTML5・javascript】

公開日: : 最終更新日:2014/08/14 JavaScript/jQuery, 画像処理

スポンサーリンク

調べてみるとCanvasをリサイズするようなjavascriptの関数は存在しないようなので自前で作るか他の方が作られたのを使うしかないようです。

今回は私の方で簡単な方法ではありますがリサイズ関数を作りました。ただし、それをするには一度画像をURLに戻して読み直すという処理が必要で、どうしても同期的に行うというのは難しいようです。また、見た目だけであればスタイルをいじるだけの方法もあります。

画像をリサイズさせる

まずは普通に

タイトルがちょっと不適切かもしれませんが普通に画像をリサイズしました。

var CanvasResize = function(canvas,width,height,func){
    var img = new Image();
    img.onload = function(){
        canvas.width = width;
        canvas.height = height;
        var ctx = canvas.getContext('2d');
        ctx.drawImage(img,0,0,width,height);
        if(func){ func(); }
    }
    img.src = canvas.toDataURL();
}

//ページ読み込み後の処理
window.addEventListener("DOMContentLoaded", function(){
    var canvas = document.getElementById('canvas');
    var context = canvas.getContext('2d');

    //画像の初期読み込み
    var img = new Image();
    img.onload = function(){
        var width = img.width;
        var height = img.height;
        //↑このサイズを任意の値にしてもリサイズされる
        canvas.width = width;
        canvas.height = height;
        context.drawImage(img, 0, 0,width,height);

        //リサイズする
        CanvasResize(canvas,300,300,function(){
                alert("完了");
        });        
    }
    img.src = "sample.jpg";
});

サンプルは読み込んだsample.jpgを一度toDataURLでURLに戻してからonloadイベントを待ち、300×300の画像にリサイズした後「完了」とアラートを出しています。本来であればアラートを出すところにリサイズ後のなんらかの処理がはいります。

Canvasを画像と一緒にリサイズするには単にCanvasのサイズ(width,heightプロパティ)を変更するだけではだめでそのサイズにしたのちに改めて画像を描画(drawImage)しないと思い通りにはいかないようです。なので、初めから指定のサイズにしたいのならば初めのonloadイベント内でキャンバスサイズを代入してもいけます。

また、Imageクラスの画像の読み込みを待つためにonloadイベントを使っていますがこれがあるためにどうしても非同期的処理になってしまいます。

jQuery.Deferredを使う

前述の方法では処理が完了した後にコールバック関数が呼ばれるといった仕組みになっていました。これはこれでいいと思いますし、この例では分かりませんが、もし他の複数のコールバック関数を使用してネストが重なると非常にみずらいコードになってしまいます。

このような非同期処理の複雑さを軽減するためにどうするべきか様々な議論が行われているようですが今回はjQueryのVer1.5から導入されているというjQuery.Deferredを使ってみました。

これの良いところはチェーン式でコールバックが書けるところにあります。

var CanvasResize = function(canvas,width,height){
    var def = $.Deferred();
    var img = new Image();
    img.onload = function(){
        canvas.width = width;
        canvas.height = height;
        var ctx = canvas.getContext('2d');
        ctx.drawImage(img,0,0,width,height);
        def.resolve(canvas);
    }
    img.src = canvas.toDataURL();
    return def.promise();
}

//ページ読み込み後の処理
window.addEventListener("DOMContentLoaded", function(){
    var canvas = document.getElementById('canvas');
    var context = canvas.getContext('2d');

    //画像の初期読み込み
    var img = new Image();
    img.onload = function(){
        var width = img.width;
        var height = img.height;
        canvas.width = width;
        canvas.height = height;
        context.drawImage(img, 0, 0, width, height);

        //リサイズする
        CanvasResize(canvas,300,300).then(function(){
                alert("完了");
        });        
    }
    img.src = "sample.jpg";
});

リサイズ処理をした後に同じようにアラートを出していますが、戻り値のthenメソッドがコールバックで呼び出されるようになっています。リサイズ関数内ではいったんpromiseオブジェクトを返したのちにresolveメソッドに値を代入すると処理が終了してthenが呼ばれるようになっています。

このthenメソッドですが、チェーン式に使えるようになっているので次のような使い方も可能です。

        //リサイズする
        CanvasResize(canvas,300,300).then(function(){
                alert("完了");
        }).then(function(){
                alert("完了2");
        });   

「完了」の後に「完了2」が呼ばれるようになっています。ただし、then内のメソッドの非同期処理は待たずに次のthenに移行してしまうようなので両方待たせたいときには「$.when」を用いるとできます。

ただし、ちょっと便利そうに見えますが結局はコールバックが入ってしまうのでものすごい便利かは使い道によるのだと思います。(もっとすごい使い方があるのだと思います)

通常の同期処理のように使いたい場合は「co」や「task.js」というものがあるそうです。

スタイルでサイズを変更する

画像そのもののサイズは割とどうでもよくて、見栄えさえリサイズしたように変わってくれればいいという方はCSSのサイズを変更してしまった方が手っ取り早いと思います。

var CanvasResizeCSS = function(canvas,width,height){
    canvas.style.width = width;
    canvas.style.height = height;
}

//ページ読み込み後の処理
window.addEventListener("DOMContentLoaded", function(){
    var canvas = document.getElementById('canvas');
    var context = canvas.getContext('2d');

    //画像の初期読み込み
    var img = new Image();
    img.onload = function(){
        var width = img.width;
        var height = img.height;
        canvas.width = width;
        canvas.height = height;
        context.drawImage(img, 0, 0, width, height);

        //リサイズする
        CanvasResizeCSS(canvas,300,300);
    }
    img.src = "sample.jpg";
});

スタイルを変更するだけなのでstyleプロパティのwidth,heightの値を変更するだけです。見た目はこれで簡単に変更できます。

デモ

元画像

画像をリサイズする

スタイルをいじるだけ

ソース

var CanvasResize1 = function(canvas,width,height,func=null){
    var img = new Image();
    img.onload = function(){
        canvas.width = width;
        canvas.height = height;
        var ctx = canvas.getContext('2d');
        ctx.drawImage(img,0,0,width,height);
        if(func){ func(); }
    }
    img.src = canvas.toDataURL();
}
var CanvasResize2 = function(canvas,width,height){
    canvas.style.width = width;
    canvas.style.height = height;
}
window.addEventListener("DOMContentLoaded", function(){
    var canvas = document.getElementById('canvas');
    var canvas1 = document.getElementById('canvas1');
    var canvas2 = document.getElementById('canvas2');
    var context = canvas.getContext('2d');
    var context1 = canvas1.getContext('2d');
    var context2 = canvas2.getContext('2d');

    //画像の初期読み込み
    var img = new Image();
    img.onload = function(){
        var width = img.width;
        var height = img.height;
        canvas.width = width;
        canvas.height = height;
        context.drawImage(img, 0, 0,width,height);

        canvas1.width = width;
        canvas1.height = height;
        context1.drawImage(img, 0, 0,width,height);

        canvas2.width = width;
        canvas2.height = height;
        context2.drawImage(img, 0, 0,width,height); 
    }
    img.src = "http://mementoo.info/img/sample.jpg";

    var btn = document.getElementById("resizebtn");
    btn.addEventListener("click",function(){
        var canvas1 = document.getElementById('canvas1');
        var canvas2 = document.getElementById('canvas2');
        CanvasResize1(canvas1,100,100);
        CanvasResize2(canvas2,100,100);
    });
});


元画像
<canvas id="canvas"></canvas>

<input type="button" id="resizebtn" value="リサイズする"/>

画像をリサイズする
<canvas id="canvas1"></canvas>

スタイルをいじるだけ
<canvas id="canvas2"></canvas>

※実はWordPressだけだと思うのですがcanvasタグに勝手にデフォルトでwidth属性、height属性が付与されてしまっているのでタグ内のスタイル変更(element.style.width,element.style.height)は重複して無効になってしまいました。なのでソースではそのままにしていますが実際はjqueryを使ってcssを変更するようにしています。

スポンサーリンク
Amazon
  • このエントリーをはてなブックマークに追加

関連記事

jThree.jsやThree.jsでcanvasの画面をキャプチャして画像にする方法

WebGLのライブラリであるThree.jsやそのラッパーライブラリのjThree.jsでcanva

記事を読む

OpenCV3.1をopencv_contrib付きでVisual Studio2013でビルドしてインストールする

はじめに OpenCV3.1でトラッキングがしたいと思いインストーラでインストールしたのですが、ど

記事を読む

【HTML/jQuery UI】NumericUpDownを設置する【Spinner】

HTMLタグにNumericUpDownがないか探したのですがないみたいなのでそれが使えるようなもの

記事を読む

【3DCG・MMD】カメラレンズによる見え方シミュレータ作成について

カメラのレンズが違うことでどのくらい出来上がる写真に差が出てくるのかを確かめることのできるシミュレー

記事を読む

monacaでWebサイトをアプリ化

monacaを使ってWebサイトをアプリ化するための叩き台としてのメモです。 Webサイトのア

記事を読む

jQueryで要素にappendとafterを使って追加する

jqueryのappendは要素の末尾に指定要素を追加し、afterは要素の後に指定要素を加えます。

記事を読む

【jQuery】大量の画像で重くなったページを遅延ロードで軽くする方法【Lazy Load】

画像をふんだんに使っているページでは読み込みの際に非常に時間がかかるという問題点があります。数枚なら

記事を読む

【javascript】RGB⇔カラーコード変換ライブラリ

RGBをカラーコードに変換、または、カラーコードをRGBに変換したい場合が出てきたのでどういうも

記事を読む

OpenCV3.1のTracking APIでトラッキングを試す

はじめに 先日OpenCV3.1をopencv_contrib付きでインストールしてTrackin

記事を読む

【javascript/jQuery】JSON形式のデータの表示確認をする

PHPであれば「var_dump」や「print_r」などでJSON形式のデータの中身が思い通りの者

記事を読む

【Laravel5】既存のDBからデータを取得して表示する

はじめに 今まで作ったWebサイトをLaravel5で見れるようにし

【C++/OpenCV】cv::Matの画像にインパルスノイズを付加する

OpenCVで画像にノイズを付け足したいと思って調べたところ、Pyth

Intel Corei7-7700TでHTC Viveの動作確認

はじめに HTC ViveというVRヘッドセットで遊んでみたのでその

【Python】フォルダ内のカッコ付き数字ファイルを一括でリネームするスクリプト

はじめに タイトルどおりなのですが、指定フォルダ内のファイルのファイ

OpenCV3.1のTracking APIでトラッキングを試す

はじめに 先日OpenCV3.1をopencv_contrib付きで

パソコンを複数台使う際便利なツール

はじめに 先日、機械学習用にGPUを積んだBTOパソコンを購入しまし

OpenCV3.1をopencv_contrib付きでVisual Studio2013でビルドしてインストールする

はじめに OpenCV3.1でトラッキングがしたいと思いインストーラ

→もっと見る

  • Author : ががんぼ
    プログラミングやWeb関係で気付いたことについてメモしていく予定。だいたいが備忘録ですが、自分でサンプルを作って動かしてみたりしています。
PAGE TOP ↑