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

関連記事

【javascript/jQuery】Progressbarで処理の進捗状況を表示する

jQuery UIでProgressbarを使う 処理経過を表示する場合プログレスバーにより提示さ

記事を読む

【jquery】iframe内のスクロールイベント設定とスクロール量取得

ページ内に設置したiframeのスクロールイベントおよびスクロール量を取得したかったのでメモ

記事を読む

WordPressの記事内でJavaScriptを動かす

WordPressでは厄介なことにJavaScriptが動かない場合があります。この記事では動かない

記事を読む

【jQuery】クリックイベントでマウスホイールクリックを検知する

$("a").click(function(){ … }); によりクリックイベントを関連付け

記事を読む

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

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

記事を読む

javascriptで画像処理をする【HTML5】

HTML5でjavascriptを使って画像処理をしてみました。このページでは手始めにグレースケール

記事を読む

PHPでページリロードをしようと思ったができなかったので

header("Location: ".$_SERVER); とすればページをリロードでき

記事を読む

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

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

記事を読む

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

やりたいこと 最近SoftEtherという筑波大学発のベンチャー企業が立ち上げたVPNサービスとい

記事を読む

Google Maps JavaScript API v3でマップ上に線を引く

GoogleMapsAPIを使って地図上に線を引いたときに気を付けたことなどをメモしておきます。

記事を読む

NVIDIA DIGITSをSupervisorを使って自動起動する

はじめに 先日Ubuntu14.04にDIGITS 5をGPUなしP

【2017年度】GeForce 1080 Ti搭載BTOパソコン比較

はじめに 最近ディープラーニング用にGPUのないPCにDIGITSを

Windows用のシンプルなストップウォッチソフト紹介

Windows(10)でも使える使いやすいKAZAMITimerという

MNISTをDIGITS 5のCPUのみで試す(GPUなし)

はじめに DIGITSを使えばGUI操作で簡単にディープラーニングが

Windowsユーザが初めてMacBookを購入したときの注意点や感想

最近12インチのMacBookを購入しました。今までWindowsしか

Redmine3.2をUbuntu14.04にインストールして躓いた所についてメモ

はじめに Ubuntu14.04 ServerにRedmine3.2

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

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

→もっと見る

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