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

関連記事

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

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

記事を読む

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

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

記事を読む

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

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

記事を読む

YoutubeのURLリンクを外部プレイヤーのものに正規表現で置換する

Youtubeのアドレスを正規表現を使って抽出して外部プレイヤーのフレームに変換・置換するスクリプト

記事を読む

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

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

記事を読む

jQueryのカラーピッカーライブラリFarbtastic Color Pickerを使う

.farbtastic .wheel { background: url(http://mem

記事を読む

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

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

記事を読む

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

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

記事を読む

【jQuery】サイドバー固定に役立つサイト集

縦スクロール 縦方向にスクロールして指定の位置に来たら要素を固定させる方法のリンク集を紹介させてい

記事を読む

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

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

記事を読む

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

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

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

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

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

→もっと見る

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