3-5 CGサンプルの解説

HTML5の醍醐味は何と言っても Canvas要素 が加わり描画機能が強化されたことです。 本項では動的なCG描画を行うソースコードを2つ公開し、使っているテクニックを紹介します。


(1)電脳世界CG

画像ファイルは用いず、ソースコードのみで描画しています。

ソースコードは次のようになります。
01<!DOCTYPE html>
02<html lang="ja">
03<head>
04<meta charset="utf-8">
05<title>JavaScript CG program (C)WorldWideSoftware</title>
06</head>
07<body style="background-color:#000;">
08<canvas id="bg"></canvas>
09<script>
10var canvas = document.getElementById("bg");
11var cnt = canvas.getContext("2d");
12var winW = 0, winH = 0, fSize, hexR;
13var tmr = 0;
14var cx = 0, cy = 0;
15var code = [];
16for( var i = 0; i < 100; i ++ ) {
17 code[i] = "";
18 for( var j = 0; j < 8+rnd(12); j ++ ) code[i] = code[i] + " " + (16+rnd(240)).toString(16);
19}
20function toInt( val ) { return Math.floor(val); }
21function rnd( max ) { return toInt(max*Math.random()); }
22function col( cr, cg, cb ) { return "rgb("+toInt(cr)+","+toInt(cg)+","+toInt(cb)+")"; }
23function drawHex( x, y, r ) {
24 var i, px, py;
25 cnt.beginPath();
26 for( i = 0; i < 6; i ++ ) {
27  px = x + toInt(r*Math.cos(Math.PI*2*60*i/360));
28  py = y + toInt(r*Math.sin(Math.PI*2*60*i/360));
29  if( i == 0 ) cnt.moveTo(px,py); else cnt.lineTo(px,py);
30 }
31 cnt.closePath();
32}
33
34window.onload = drawBG();
35function drawBG() {
36 var i, x, y;
37 if( winW != window.innerWidth || winH != window.innerHeight ) {
38  winW = window.innerWidth;
39  winH = window.innerHeight;
40  fSize = toInt((winW+winH)/80);//文字の大きさ
41  hexR = toInt((winW+winH)/40);//ヘキサの半径
42  canvas.width = winW;
43  canvas.height = winH;
44  cnt.font = fSize + "px monospace";
45 }
46 tmr ++;
47 //バックの塗り潰し
48 cnt.fillStyle = "#000";
49 cnt.fillRect( 0, 0, winW, winH );
50 //ヘキサ
51 cnt.lineWidth = 1+hexR/40;
52 y = -(hexR*1.732)*(tmr%50)/50;
53 x = hexR*0.5;
54 i = 0;
55 while( y < winH ) {
56  cnt.fillStyle = cnt.strokeStyle = col( 255*y/winH, 255*x/winW, 64 );
57  drawHex( x, y, hexR*0.95 );
58  if( rnd(100) < 3 ) cnt.fill(); else cnt.stroke();
59  x += hexR*3;
60  if( x > winW ) {
61   i = 1-i;
62   x = hexR*(0.5+1.5*i);
63   y += hexR*1.732/2;
64  }
65 }
66 //サークル
67 x = cx;
68 y = cy;
69 if( tmr%50 == 0 ) {
70   cx = rnd(winW);
71   cy = rnd(winH);
72   cnt.strokeStyle = "#fff";
73   cnt.beginPath();
74   cnt.moveTo(x,y);
75   cnt.lineTo(cx,cy);
76   cnt.stroke();
77 }
78 else {
79  for( i = 2; i <= 9; i ++ ) {
80   cnt.strokeStyle = col(24*i,24*i,24*i);
81   cnt.beginPath();
82   cnt.arc( x, y, hexR*(10-i), (tmr+i)/2, (tmr+i)/2+3.14, false );
83   cnt.stroke();
84  }
85 }
86 //マシン語
87 cnt.strokeStyle = "#4af";
88 cnt.lineWidth = 1;
89 y = fSize*2;
90 i = tmr%100;
91 while( y < winH ) {
92  cnt.strokeText( code[i], 10, y );
93  i = (i+1)%100;
94  y += fSize*2.4;
95 }
96 setTimeout( drawBG, 100 );
97}
98</script>
99</body>
100</html>

ブラウザのサイズが変わった時にキャンバスの大きさをセットし直しています(37~45行) スマートフォンやタブレットでは持ち方を変えた時(縦持ち⇔横持ち)に機能します。

ヘキサを描く関数を抜粋します。 3-1(3) で解説した三角関数を用いて6つの点を結んで描いています。

function drawHex( x, y, r ) {
 var i, px, py;
 cnt.beginPath();
 for( i = 0; i < 6; i ++ ) {
  px = x + toInt(r*Math.cos(Math.PI*2*60*i/360));
  py = y + toInt(r*Math.sin(Math.PI*2*60*i/360));
  if( i == 0 ) cnt.moveTo(px,py); else cnt.lineTo(px,py);
 }
 cnt.closePath();
}

この図形を1行ごとに互い違いに並べる位置とし(61,62行の計算)、画面全体に描画しています。


(2)宇宙空間CG

背景の星々と銀河の画像を用い、宇宙を表現しています。

ソースコードは次のようになります。
01<!DOCTYPE html>
02<html lang="ja">
03<head>
04<meta charset="utf-8">
05<title>JavaScript CG program (C)WorldWideSoftware</title>
06</head>
07<body style="background-color:#000;">
08<canvas id="bg"></canvas>
09<script>
10var canvas = document.getElementById("bg");
11var cnt = canvas.getContext("2d");
12var winW = 0, winH = 0;
13var tmr = 0;
14
15//画像ファイル読込
16var img = [], imgPre = [];
17function loadImg( n ) {
18 imgPre[n] = false;//読み込みできたかのフラグ
19 img[n] = new Image();
20 img[n].src = "jscg02_" + n + ".png";
21 img[n].onload = function() { imgPre[n] = true; }
22}
23loadImg(0);
24loadImg(1);
25
26window.onload = drawBG();
27function drawBG() {
28 tmr ++;
29 if( winW != window.innerWidth || winH != window.innerHeight ) {
30  winW = window.innerWidth;
31  winH = window.innerHeight;
32  canvas.width = winW;
33  canvas.height = winH;
34 }
35 //星々
36 if( imgPre[0] ) {
37  var y = tmr%(Math.floor(winH));
38  cnt.drawImage( img[0], 0, y-winH, winW, winH );
39  cnt.drawImage( img[0], 0, y, winW, winH );
40 }
41 //銀河
42 cnt.save();
43 cnt.translate( winW/2, winH/2 );
44 cnt.scale( winW/100, winW/400 );
45 cnt.rotate( Math.PI*tmr/180 );
46 if( imgPre[1] ) cnt.drawImage( img[1], -60, -60 );
47 cnt.restore();
48
49 setTimeout( drawBG, 100 );
50}
51</script>
52</body>
53</html>

使っている画像は次の2つです。
jscg02_0.png
jscg02_1.png

銀河の画像を回転させる処理がポイントです。その部分を抜粋します。

 cnt.save();
 cnt.translate( winW/2, winH/2 );
 cnt.scale( winW/100, winW/400 );
 cnt.rotate( Math.PI*tmr/180 );
 if( imgPre[1] ) cnt.drawImage( img[1], -60, -60 );
 cnt.restore();

3-1 で解説した回転方法を用います。今回は scale命令を使い、Y方向の比率をX方向の1/4とし、銀河を俯瞰で見た感じを表現しました。
原点をキャンバス中心に移動 → 縦横比を設定 → 回転 → (-60,-60)の位置に画像を表示 という手順でこの描画を実現しています。 銀河の画像サイズは横120ドット、縦120ドットですので、(-60,-60)の位置に描画して中心で回るようにしています。

本講座で最後まで学んで下さった皆さんは、プログラミング技術の基礎がしっかり身に着いたことと思います。 皆さんがコンピューターの世界で活躍されることを期待し、本講座はこれで一旦終了致します。 ご要望を頂ければプラスアルファの解説を用意致します。ご意見、ご質問等、何なりと下記アドレスまでご連絡下さい。



前のページへ

お気軽にお問い合わせ下さい →