« 2011年5月 | トップページ | 2013年10月 »

2012年5月

JavaScript:excanvasを使ってWebページに画像を表示する

【概要】
JavaScriptでWeb上にグラフィックを描く技術に「Canvas」があります。
Canvasは現在IE9,FireFox,Google Chrome,Safariなどで実装されていますが,IEは8以前では実装されていません。
IEの8以前でCanvasの機能を使うために,Googleから「excanvas」というライブラリが公開されています。
今回のエントリでは,excanvasを使って画像データを表示させたときに嵌ったところを紹介します。

●excanvasの参照
嵌ったところではありませんが,excanvasはjavascriptで書かれた外部ファイルなので,HTMLのheader内で参照する必要があります。
このとき,ネットで見つかるサンプルの多くは以下のようなコードになっています。

<!--[if IE]>
<script type="text/javascript" src="js/excanvas.min.js"></script>
<![endif]-->

しかしながら,canvasはIE9で実装されているので,IE9ではexcanvasは不要です。
なので次のように書くべきかと思います。

<!--[if lt IE 9]>
<script type="text/javascript" src="js/excanvas.min.js"></script>
<![endif]-->

●画像の読み込み
画像データはImageクラスで読み込んで,読み込みが完了してから描画を行います。
この処理でよく見かけるサンプルコードは以下のようなものです。

var image = new Image();
image.src = 'path/filename.jpeg';
image.onload = function () {
  // 画像描画処理.
};

このコードは,画像ファイルを読み込んで,読み込みが完了したらonloadの中の画像描画処理が実行される,という動作を意図したものです。Canvasの画像描画は事前に画像データの読み込みが完了していなければならないので,このような処理になります。
このコードはブラウザによってはうまく動作しますが,Imageクラスの使用方法としては誤りのようです。少なくともIE8ではonloadは呼ばれませんでした。
誤っている点ですが,Imageクラスではsrcにパスを指定するより前にonloadを設定しなければならないようです。正しいコードは以下になります。

var image = new Image();
image.onload = function () {
  // 画像描画処理.
};
image.src = 'path/filename.jpeg';

●同一イメージファイルを何度も読み込む場合
IE8以前でImageクラスを使った場合,一度画像データを読み込んでキャッシュされた状態で同じ画像ファイルを読み込もうとすると,onloadの処理が呼ばれず画像描画処理が実行されない問題があるようです。
この問題の対処方法としてよく見かけるのは,ファイルパスの最後に「?+ランダムな値」を付加して同一のファイルを毎度異なるファイル名で読み込む方法です。
他の方法では,試してはいませんが,jQueryのempty()関数はキャッシュも削除するようなので,これで対処できる可能性があります。

●canvasエレメントをcreateElementで作った場合の問題
canvasエレメントをdocument.createElementで生成した場合,excanvasの環境ではcanvasエレメントとして初期化されず,canvasエレメントにあるはずのgetContext関数が存在しない状態になってしまいます。このような場合はexcanvasの初期化関数を使って明示的に初期化する必要があります。canvasタグをHTMLファイルに直接書いた場合は,初期化コードが自動的に実行されるので問題は起きません。

var canvas = document.createElement('canvas');
if (typeof G_vmlCanvasManager !== 'undefined') {
  canvas = G_vmlCanvasManager.initElement(canvas);
}

なお,G_vmlCanvasManager.initElementは引数のcanvasエレメントが初期化済みかチェックするので,すでに初期化されたエレメントを渡しても問題ありません。また,G_vmlCanvasManagerはexcanvas固有のクラスなので,Canvasが実装されていてexcanvasを使用しない環境でこのコードを実行しても,G_vmlCanvasManagerの存在確認をすれば問題ありません。

Imageクラスの問題とcanvasエレメントの問題に対処したコードは以下のようになります(一部jQueryを使っています)。

var parent = document.getElementById('parentElementId');
$(parent).empty();

var image = new Image();
image.onload = function () {
  var canvas = document.createElement('canvas');
  $(parent).append($(canvas).attr('id','canvasElementId'));

  if (typeof G_vmlCanvasManager !== 'undefined') {
    canvas = G_vmlCanvasManager.initElement(canvas);
  }
  if (canvas.getContext) {
    var context = canvas.getContext('2d');
    context.drawImage(this, 0, 0, this.width, this.height);
  }
};
image.src = 'path/filename.jpeg';
※ image.onload=function() {...}内ではimageインスタンスは「this」で参照できます。

■参考URL
Googleのexcanvas配布元:http://excanvas.sourceforge.net/
HTML5.jpのCanvasドキュメント:http://www.html5.jp/canvas/index.html
mozillaのCanvasドキュメント:https://developer.mozilla.org/ja/Canvas_tutorial/Using_images

■関連書籍をAmazonで検索:[Canvas]
HTML5 Canvas

にほんブログ村 IT技術ブログへ にほんブログ村 IT技術ブログ プログラム・プログラマへ 人気ブログランキングへ ←この記事が役に立ったという方はクリックお願いします。


ノートンモバイルセキュリティバナー

| | トラックバック (0)

C言語:TRUEとFALSEの値

【課題】
以前どこかで次のようなCのコードを見たことがあります。

if (flag == TRUE) {
  処理1
}
else if (flag == FALSE) {
  処理2
}
else {
  処理3
}

ここで「処理3」は実行されることがあるのか?というのが今回のエントリのテーマです。

【考察】
まず最初に,C言語におけるbooleanについての確認です。
Cのbooleanには2つの定義があります。

●booleanの定義その1:条件分岐の判定
if文,for文,while文など,値がtrueかfalseか判定して条件分岐を行う場合のtrue/falseの値については,Cの解説書に書かれていてよく知られています。falseは「0」,trueは「0以外」です。1,2,3…及び-1,-2,-3…はすべてtrueです。

●booleanの定義その2:比較演算子の演算結果
比較演算子の演算結果はtrue/falseのどちらかになりますが,Cでは元々boolean型がなく,この演算結果には数値が割り当てられます。
この数値の具体的な値を確認するには,たとえば以下のようなコードで確認できます。

int flag = (int)(a == b);

aとbに値を設定して,この変数flagにどのような値が入るかprintfで表示させるなどして確認してみましょう。

aとbが等しい場合,これは値が「1」になるはずです。「true」の値は「1」です。
aとbが等しくない場合,これは値が「0」になるはずです。「false」の値は「0」です。

●TRUEとFALSEの値は?
FALSEの値は0でいいでしょう。TRUEの値は実際の値を確かめてみると「1」が定義されています。
TRUEが1であることについては以下のような合理的理由があるかと思います。
1)定義1ではtrueの値は「0以外」だが,TRUEは特定の値にならざるを得ない。
2)定義2ではtrueの値は「1」なので,TRUEの値を「1」にすると定義2のtrueと直接比較できる。

【結論】
TRUEが1,FALSEが0であることから,最初のコードは以下のコードと同等です。

if (flag == 1) {
  処理1
}
else if (flag == 0) {
  処理2
}
else {
  処理3
}
ここでflagの値が0,1以外の値であった場合は処理3が実行されることがわかります。 結論としては処理3が実行されることはありうる,ということになります。

定義その1で条件判定する場合は,以下の書き方でなければならない,ということになるかと思います。

if (flag) {
  処理1
}
else {
  処理2
}

どうしてもTRUE/FALSEを使いたい,という場合は以下のように書くことになるかと思います。

if (flag != FALSE) {
  処理1
}
else {
  処理2
}


■関連書籍をAmazonで検索:[C言語]
C実践プログラミング 第3版

にほんブログ村 IT技術ブログへ にほんブログ村 IT技術ブログ プログラム・プログラマへ 人気ブログランキングへ ←この記事が役に立ったという方はクリックお願いします。
Bose SoundTrue in-ear headphones smartphone

| | トラックバック (0)

« 2011年5月 | トップページ | 2013年10月 »