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
  • このエントリーをはてなブックマークに追加

関連記事

チェスボード画像自動生成ツール

1マスのサイズ(ピクセル) マスの数× 左上が白 枠をつけるか 枠の色白黒

記事を読む

ニコニコ動画のURLリンクから外部プレイヤーのスクリプトに正規表現で置換する

ニコニコ動画の動画のアドレスを抽出して外部プレイヤー貼りつけソースのスクリプトに変換するソースです。

記事を読む

【jQuery UI】タブをクリックしたときのイベントでselectが使えない

jQuery UIは1.10のバージョンではタブをクリックしたときのイベントの名前が変わっているよう

記事を読む

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

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

記事を読む

AmazonのランキングRSSから画像リンクを作る

Amazon RSS Amazonでいい感じのRSSが無いかと探していたのですが実は本家に素晴らし

記事を読む

スマホ向け幅固定サイトの回転時の幅対応方法

幅固定サイトでのスマホ回転時Webサイトの横幅を合わせる方法のメモ。 下記2点の設定が必要です。

記事を読む

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

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

記事を読む

ニコニコ動画の外部プレイヤーを動的に設置する【javascript/jQuery】

ニコニコ動画の外部プレイヤーはページのはじめの読み込みのときにしか表示されず、javascriptで

記事を読む

【Three.js/jThree.js】カメラ内部パラメータを変更して視野などを変える

jThree.jsでカメラの内部パラメータを変更するのに手間取ったのでメモ。参考にしているjThre

記事を読む

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

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

記事を読む

UWSCを使ったソフト自動立ち上げ【SoftEther VPN Server】

やりたいこと 最近SoftEtherという筑波大学発のベンチャー企業

【PHP】headerでContent-Typeを指定したのに効かない場合の対処法

PHPでサイトマップを作ろうと思い、XML形式のファイルを出力しようと

スマホ向け幅固定サイトの回転時の幅対応方法

幅固定サイトでのスマホ回転時Webサイトの横幅を合わせる方法のメモ。

【PHP】特定のURLからそのAtomやRSSのフィードを抽出する方法

特定のURLからRSSやATOMのフィードを抽出する方法をメモ。 流

フィード抽出ツール(RSS1.0、RSS2.0、atom)

任意URL サイト名 サイトURL RSS1.0

格安プラン限定レンタルサーバー機能比較表(2016年)

はじめに  最近新しい共用サーバーをレンタルしようと思い調査およびそ

kindle unlimitedが便利だったのでお勧めの使い方など感想メモ

 kindle unlimitedというサービスが8/3からAmazo

→もっと見る

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