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を変更するようにしています。

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

関連記事

WordPressサイトのSSL対応(HTTPS化)手順のまとめ【さくらサーバー】

先週頃にこのサイトをSSL対応しましたのでその流れについてまとめておき

【Google Charts】動的にグラフを更新する方法

はじめに Webサイト上でグラフを描こうと思った場合、いくつかのJa

体重変化量計算シミュレータ【ダイエット/肥満】

ツール本体 入力 カロリー入力 1日の余剰摂取/消費カロリー

おサイフケータイ対応ストレージ32GBのSIMフリースマホまとめ【2017年秋版】

はじめに SIMフリーの格安スマホのおサイフケータイ機能付きのもので

リクルート期間限定ポイントの有効な使い道

はじめに  先日クレジットカードの見直し活動の一環でポイント還元率の

初心者がお金を貯めるための節約・財テク手法まとめ【ポイント還元・投資・税金対策】

はじめに  最近なるべく節約しようと思い、お金周りに関して色々調べて

動画講座を効率的にキャプチャして復習する方法

はじめに  最近、動画媒体の講座などをたまに視聴しています。独学だと

→もっと見る

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