Skin:
[NORMAL]
[BLUE] [DOS] [LIGHT]  / コピーするための表示 / 実行
このファイル: /home/web6047/www/cgi-bin/prj/20180901-indexJS/a.js
1 /*
2 どうなっているのか?
3
4 App()
5 App.onloadx() htmlのonloadで呼ばれる。画像のプリロードからも呼ばれ、loadをカウントしてる。
6 App.onloadx1() htmlとimageのloadが完了したら呼ばれる。固定的な内容。onloadx2を呼ぶ。
7 App.onresizex() 固定的な内容。通常は変更しないと思う。
8 App.onloadx2() ★ここから書く★
9 App.start() stopをクリックした後再開するとき呼ばれる。
10 App.run() 書いたもの。消しても良い
11 App.draw() 書いたもの。消しても良い
12
13 【説明】
14
15 このファイルを html ファイルの script タグの src 属性で指定するだけで、動作開始するように作ったつもり。
16 目的のソフトウェアを App というクラスにまとめてある。
17 コメントで、「以下 変更しない部分」、「以下 変更する部分」のようにファイルを大きく2分してある。
18 このファイルを再利用するためです。
19
20 html の読み込みが完了した時点で、App クラスの onloadx1() 関数が呼ばれる。
21
22 onloadx1() と onloadx2() は処理的に分ける必要はないが、変更する必要のない部分と、
23 目的のソフトウェアを実装する部分とに分別するために分けた。
24
25 リサイズされたら、目的の部分(canvas 要素)はサイズを自動で合わせるようになっている。
26
27
28 【目的のソフトウェア 部分】
29
30 ページのロードが完了すると、このプログラムは画面に大きく、多数の四角形の 3DCG を描画する。
31 右上の STOP ボタンで停止と再開を行う。
32
33 アニメを行う基本的なプログラムになっている。
34
35 onloadx2() で 3DCG の各モデルの定義を行い、その後すぐに draw() している。
36 つづく start() でアニメが開始される。( setInterval() による run() の定期実行を行う)
37
38 run() は各アニメの数値の推移を行い、
39 "すい星"(大きな四角形の後に小さな四角形がパラパラと続く様子)
40 の尾の作成、消去など行い、最後に draw() している。
41
42 draw() は 3DCG の描画の基本的なプログラムが書かれている。
43
44 1. 画面に描く各四角形の4頂点の座標計算
45 2. 奥から手前の順になるようにソート(画家のアルゴリズム)
46 3. 描画
47
48 webGL やその他 3DCG などのライブラリは一切使用していません。
49
50
51 */
52
53 //---以下 変更しない部分
54
55 /*
56 <tag1 id="whiteareaID"> → relative, z-index=0; に変更される
57 <div>STOPやSPEEDなどのリンク</div> 自動作成される
58 <canvas></canvas> 自動作成される
59 </tag1>
60 */
61
62 var indexjs = new App();
63 App.prototype.onloadx = function( e ) {
64 this.onloadxCount++;
65 console.log( this.onloadxCount + " / " + this.onloadxCountMax );
66 //check.
67 if( this.onloadxCount == this.onloadxCountMax ) {
68 var parentEL = document.getElementById( "whiteareaID" );
69 this.onloadx1( parentEL ); //onloadx1は最後にonloadx2を呼んでいる
70 }
71 };
72
73 //ページ読み込み完了で開始
74
75 //---画像プリロード
76
77 indexjs.images = {
78 "red" : "20180901-indexJS/imgs/red.png",
79 "green" : "20180901-indexJS/imgs/green.png",
80 "blue" : "20180901-indexJS/imgs/blue.png",
81 "mountainLeft" : "20180901-indexJS/imgs/mountainLeft.png",
82 "title" : "20180901-indexJS/imgs/title.png",
83 }
84 indexjs.onloadxCount = 0;
85 indexjs.onloadxCountMax = Object.keys( indexjs.images ).length + 1;
86 for( var name in indexjs.images ) {
87 var src = indexjs.images[ name ];
88 indexjs.images[ name ] = new Image();
89 indexjs.images[ name ].onload = indexjs.onloadx.bind( indexjs );
90 indexjs.images[ name ].src = src;
91 }
92 addEventListener( "load", indexjs.onloadx.bind( indexjs ) );
93
94
95 function App() { //Appクラスのコンストラクタ
96 this.name = "test";
97 }
98
99 App.prototype.onloadx1 = function( parentEL ) {
100 /*
101 固定的な内容。
102 */
103 console.log( "onloadx1()" );
104
105 this.speedstep = [ 10, 75, 200, 500 ];
106 this.timerMS = this.speedstep[ 1 ];
107
108 //(※正直言うとcanvasのサイズについて多少混乱中…)
109
110 //check.
111 if( ! parentEL ) parentEL = document.getElementsByTagName( "body" )[ 0 ];
112
113 //canvasを置く親要素
114 this.parentEL = parentEL;
115 with( this.parentEL.style ) {
116 position = "relative";
117 zIndex = 0;
118 }
119
120 //アニメの停止ボタン 親要素の上部に配置
121 this.swEL = document.createElement( "div" );
122 this.parentEL.appendChild( this.swEL );
123 with( this.swEL.style ) {
124 border = "solid 0px black";
125 position = "absolute";
126 right = "0px";
127 top = "0px";
128 boxSizing = "border-box";
129 zIndex = 2;
130 padding = ".5em 1em";
131 }
132 this.swEL.innerHTML = "";
133 this.swEL.innerHTML += "<a style='color:black;' href=\"javascript:if( indexjs.timerID ) indexjs.stop(); else indexjs.start(); void(0);\">STOP</a><BR>";
134 this.swEL.innerHTML += '<a style=\'color:black;\' href=%%dquote26%%>SPEED</a>';
135
136 //CANVAS要素 親要素の上部に配置
137 this.canvasEL = document.createElement( "canvas" );
138 this.parentEL.appendChild( this.canvasEL );
139 this.canvasEL.setAttribute( "id", "indexjs_canvasELID" );
140 with( this.canvasEL.style ) {
141 border = "solid 0px black";
142 position = "absolute";
143 left = "0px";
144 top = "0px";
145 boxSizing = "border-box";
146 zIndex = -1;
147
148 }
149
150
151 //true にするとドットがシャープになる。falseはアンチエイリアスが入る(通常)。IEは非対応
152 if( true ) {
153 this.canvasEL.style.imageRendering = "pixelated";
154 this.canvasEL.style.imageRendering = "optimizeSpeed";
155 }
156 this.lowmode = true;
157 this.cc = this.canvasEL.getContext( "2d" );
158
159 this.onresizex();
160
161 //resize設定
162 addEventListener( "resize", ( function( e ) { this.onresizex( e ); } ).bind( this ), false );
163
164 //canvasが画面外に出たらCPUパワーを抑えるために停止する処理
165 addEventListener( "scroll", function( e ) {
166
167 var scrollEL = document.documentElement ? document.documentElement : document.body;
168 var r = indexjs.cc.canvas.getBoundingClientRect();
169
170 if( scrollEL.scrollTop + r.top + r.height / 2 < 0 )
171 indexjs.stop();
172 else
173 if( ! indexjs.timerID ) indexjs.start();
174
175 }, false );
176
177 this.onloadx2();
178
179 }//onloadx1
180
181 App.prototype.onresizex = function( e ) {
182 console.log( "onresizex()" );
183
184 //リサイズされた親要素に合わせて、サイズ変更
185
186 var wa = this.parentEL;
187 var waRect = wa.getBoundingClientRect();
188 this.canvasW = Math.round( waRect.width );
189
190 //最初のh2タグに合わせる
191 var htags = document.getElementsByTagName( "h2" );
192 if( htags.length > 0 ) {
193 this.canvasH = Math.round( htags[ 0 ].getBoundingClientRect().top - wa.getBoundingClientRect().top ) - 16;
194 } else {
195 this.canvasH = 480;
196 }
197
198 this.canvasEL.style.width = this.canvasW + "px";
199 this.canvasEL.style.height = this.canvasH + "px";
200 this.canvasEL.setAttribute( "width", this.canvasW );
201 this.canvasEL.setAttribute( "height", this.canvasH );
202
203
204 //true にすると解像度を下げる。false は通常。
205 if( this.lowmode ) {
206 var pixelsize = 2; //ドットの大きさ2~
207 this.canvasEL.style.width = this.canvasEL.width + "px"; //実物画面大きさとして
208 this.canvasEL.style.height = this.canvasEL.height + "px";
209 this.canvasEL.width /= pixelsize; //解像度として
210 this.canvasEL.height /= pixelsize;
211 this.cc.scale( 1 / pixelsize, 1 / pixelsize );
212 }
213
214 console.log( this.canvasW, this.canvasH );
215
216 if( e ) this.draw();
217
218 }//onresizex
219
220 //---以上 変更しない部分
221
222
223 //---以下 変更する部分 目的のソフトウェア
224
225 App.prototype.onloadx2 = function() {
226 /*
227 基本的にはここから書く
228 */
229 console.log( "onloadx2()" );
230
231 this.layers = new Array();
232 //奥
233 var layer = new Object();
234 layer.image = this.images.blue;
235 layer.px = 0;
236 layer.py = this.canvasH - layer.image.height;
237 layer.addX = 4;
238 layer.width = layer.image.width + 50;
239 this.layers.push( layer );
240 //中
241 var layer = new Object();
242 layer.image = this.images.green;
243 layer.px = 0;
244 layer.py = this.canvasH - layer.image.height;
245 layer.addX = 8;
246 layer.width = layer.image.width + 100;
247 this.layers.push( layer );
248 //手前
249 var layer = new Object();
250 layer.image = this.images.red;
251 layer.px = 0;
252 layer.py = this.canvasH - layer.image.height;
253 layer.addX = 16;
254 layer.width = layer.image.width * 1.7;
255 this.layers.push( layer );
256
257 this.onloadx3();
258 };
259
260 App.prototype.onloadx3 = function() {
261 /*
262 次の手順で呼ばれる。
263 SPEED リンク → resetメソッド → onloadx3メソッド
264 SPEEDリンクは indexjs.timerMS の値を変更する。
265 */
266 console.log( "onloadx3()" );
267
268
269
270 this.draw();
271 this.start();
272 }
273
274 //--- タイマ制御系
275
276 App.prototype.start = function() {
277 console.log( "start()", this.timerMS );
278 this.timerID = setInterval( this.run.bind( this ), this.timerMS );
279 };
280 App.prototype.stop = function() {
281 if( this.timerID ) {
282 console.log( "stop()" );
283 clearInterval( this.timerID );
284 this.timerID = null;
285 }
286 };
287 App.prototype.reset = function() {
288 this.stop();
289 this.onloadx3();
290 };
291 App.prototype.run = function() {
292 for( var i = 0; i < this.layers.length; i++ ) {
293 var layer = this.layers[ i ];
294 layer.px += layer.addX;
295 //check.
296 if( layer.px > 0 ) {
297 layer.px = -layer.width;
298 }
299 }
300 this.draw();
301 };
302
303 App.prototype.draw = function() {
304 var cc = this.cc;
305 cc.fillStyle = "blue";
306 cc.fillRect( 0,0,this.canvasW, this.canvasH );
307
308 for( var i = 0; i < this.layers.length; i++ ) {
309 var layer = this.layers[ i ];
310 var cnt = 0;
311 while( 1 ) {
312 var gx = layer.px + layer.width * cnt;
313 //check.
314 if( gx > this.canvasW ) break;
315
316 cc.drawImage( layer.image, gx, layer.py );
317 cnt++;
318 }
319 }
320
321 cc.drawImage( this.images.mountainLeft, 0, this.canvasH - this.images.mountainLeft.height );
322 var x = ( this.canvasW - this.images.title.width ) / 2;
323 var y = ( this.canvasH - this.images.title.height ) / 2;
324 cc.drawImage( this.images.title, x + 65, y );
325
326
327 cc.fillStyle = "black";
328 var step = 4;
329 for( var i = 0; i < Math.round( this.canvasH / step ); i++ ) {
330 cc.fillRect( 0, i * step, this.canvasW, Math.floor( step / 2 ) );
331 }
332 };