Skin: [NORMAL]
[BLUE]
[DOS] [LIGHT]  / コピーするための表示 / 実行
このファイル: /home/web6047/www/cgi-bin/prj/20180728-javascript/callbackを使った例(合理anmからcallback)+batch/canvas.html
1 <!DOCTYPE html>
2 <head>
3 <meta content="text/html; charset=UTF-8" http-equiv="content-type">
4 <title>UntitledHomepage6047Canvas</title>
5 <script>
6 /*
7 このスクリプトの目的:
8
9 ●1 一連のアニメを合理的にAnmにまとめている。 大きな目的。
10
11 ●2 一連のアニメの終了でcallbackが実行できている。 大きな目的。
12
13 ●3 関数での移動ができている。
14
15 */
16 console.clear();
17 console.log( "=============== script ==============" );
18 function con() { console.log( Array.prototype.join.call( arguments, " " ) ); }
19 function $( id ) { return document.getElementById( id ); }
20 var HereDocument = /\/\*\s*([^]*?)\s*\*\//;
21 // usage: var txt = ( function() { /*multiTXT*/ } ).toString().match( HereDocument )[ 1 ];
22
23
24 function onloadx() {
25
26 canvasEL = $( "canvasELID" );
27 canvas = canvasEL.getContext( '2d' );
28 screenW = canvas.canvas.width;
29 screenH = canvas.canvas.height;
30
31
32
33
34 //画面要素の作成
35 elements = new Object();
36 elements.A = new Element( 50, 300, null, null, "red" );
37 elements.B = new Element( 500, 300, null, null, "green" );
38 elements.C = new Element( 250, 300, null, null, "blue" );
39 elements.T = new TextElement( 50, 400, "" );
40
41
42 //アニメエンジン始動
43 anms = new Array();
44 timerMS = 100; //※この値が小さいほどなめらか
45 timerID = setInterval( run, timerMS );
46
47
48 //イベントプログラム 実行★
49 //これが1行1行自前のエンジンで実行されるプログラムの例
50 // //suspend はその行を実行後、エンジンは停止する。エンジンを再開するためにはどこかでresume()を実行する。
51 // //anm130 はその行を130ms遅らせて実行する。(正しくは実行後、130ms待ってから再開する…)
52 var src = function() {
53
54 testPose(); //suspend
55 mes = "スライムがあらわれた!";
56 for( var i = 0; i < mes.length; i++ ) {
57 elements.T.text = mes.substr( 0, i + 1 ); //anm130
58 draw( canvas );
59 }
60
61 }.toString().match( /\{([\s\S]*)\}/ )[ 1 ];
62
63 program = new Instruction( null, null, null, src, null );
64 program.exec();
65
66 }
67 function testPose() {
68
69 //アニメの作成 ※アニメが終了したら、callbackとして、エンジンの再開のresume()を実行する。
70 anm = new Anm( timerMS, 2000, function() { program.resume(); } ); //★
71
72 //●3 関数での移動ができている。
73
74 //どのように移動するかを定義する関数
75
76 //放物線 関数
77 f1 = function() {
78 var cnt = this.parent.cnt;
79 var cntmax = this.parent.cntmax;
80
81 var x = cnt / cntmax; //0~1
82 x -= .5;
83
84 var y = x * x * 1000;
85
86 return y;
87 }
88
89 //正弦波 関数
90 f2 = function() {
91 var cnt = this.parent.cnt;
92 var cntmax = this.parent.cntmax;
93
94 var y = Math.sin( cnt ) * 20;
95
96 return y;
97 }
98
99 //各動き
100 anm.add( elements.A, "x", elements.A.x, elements.C.x );
101 anm.add( elements.A, "y", elements.A.y, elements.C.y, f1 );
102 anm.add( elements.B, "x", elements.B.x, elements.C.x );
103 anm.add( elements.B, "y", elements.B.y, elements.C.y, f2 );
104 anms.push( anm );
105
106 }
107 function run() {
108 var drawFLG = false;
109
110 //アニメ実行
111 for( var i = 0; i < anms.length; i++ ) {
112 var anm = anms[ i ];
113
114 if( anm.step() == false ) {
115 //アニメの終了
116
117 //●2 一連のアニメの終了でcallbackが実行できている。 大きな目的。
118
119 anms.splice( i--, 1 ); //アニメ削除
120 anm.callback(); //アニメ後処理
121 continue;
122 }
123
124 drawFLG = true;
125
126 }//for i
127
128 if( drawFLG ) draw( canvas );
129 }
130 function draw( cc ) {
131 cc.clearRect( 0, 0, screenW, screenH );
132 //画面要素を描く(赤、青、緑の四角)
133 for( var name in elements ) {
134 var element = elements[ name ];
135 element.draw( cc );
136 }
137 }
138
139
140 //---クラス アニメオブジェクト
141
142 function Anm( timerMS, ms, callback ) {
143 //●1 一連のアニメを合理的にAnmにまとめている。 大きな目的。
144
145 //ひとつのアニメオブジェクトに cnt, cntmax が1組あり、
146 this.cnt = 0;
147 this.cntmax = Math.floor( ms / timerMS );
148
149 //ひとつのアニメオブジェクトに複数の動き motions があるところが、合理的。
150 this.motions = new Array();
151 this.callback = callback ? callback : function() {};
152
153 /*
154 つまり、このようにすれば、
155 複数の動きを同じ時間に開始し、終了し、終了したら callback を1回実行する
156 ということがやりやすくなる。
157
158 これをSVC(Side View Character)に例えると、あるポーズから別のポーズへ3秒で変更する場合、
159 全ての関節を3秒で回転させ、回転完了して別のポーズになったら callback を1回実行する。
160 ということがやりやすくなる。
161
162 この callback を1回実行するというのは、自作のJavaScriptエンジンからSVCのポーズアニメを実行したとき、
163 アニメの完了でcallbackを使ってエンジンへ戻る、という用途を想定している。
164 */
165
166 this.repeat = false;
167 this.reverse = false;
168 this.direction = 1;
169 }
170 Anm.prototype.add = function( element, member, sx, ex, f ) {
171
172 var motion = {
173 element : element, //アニメ対象オブジェクト
174 member : member, //アニメ対象オブジェクトの対象変数名
175 sx : sx, //アニメ開始位置
176 ex : ex, //アニメ終了位置
177 length : ex - sx, //アニメ範囲
178 parent : this, //Anm
179 f : f, //次の値計算関数
180 firstF : 0, //次の値計算関数の結果の初期値
181 isNum : element[ member ].match ? false : true, //次の値計算関数の結果は数値か、文字列か
182 };
183
184 if( f ) motion.firstF = motion.f(); //次の値計算関数の結果の初期値を定義
185
186 this.motions.push( motion );
187 };
188 Anm.prototype.step = function() {
189
190 //check. アニメの終了検知
191 if( this.reverse ) { //reverseモード時に
192
193 if( this.cnt < 0 || this.cnt > this.cntmax ) { //範囲外なら
194 this.cnt = this.direction < 0 ? 1 : this.cntmax - 1; //範囲内に戻し
195 this.direction *= -1; //方向を逆にする。
196 }
197
198 } else if( this.cnt > this.cntmax ) { //範囲外なら
199
200 return false;
201
202 }
203
204 //各動きmotionについて
205 for( var i = 0; i < this.motions.length; i++ ) {
206 var motion = this.motions[ i ];
207 with( motion ) {
208 if( isNum ) {//変更する値が数値である場合
209
210 if( f ) //関数定義がされている場合
211
212 element[ member ] = sx + f() - firstF; //←関数はここで実行
213
214 else //単純な移動 始点から目的地までの距離*進捗
215
216 element[ member ] = sx + length * ( this.cnt / this.cntmax );
217
218 } else //変更する値が文字列である場合( たとえば、"RGB(255,255,255)" など )
219
220 element[ member ] = f();
221 }//with
222 }//for i
223
224 this.cnt += this.direction;
225
226 return true;
227 };
228
229 //---クラス 画面要素オブジェクト
230
231 function Element( x, y, w, h, color ) {
232 this.x = x ? x : 0;
233 this.y = y ? y : 0;
234 this.w = w ? w : 24;
235 this.h = h ? h : 24;
236 this.color = color ? color : "black";
237 }
238 Element.prototype.draw = function( cc ) {
239 cc.fillStyle = this.color;
240 cc.fillRect( this.x, this.y, this.w, this.h );
241 cc.strokeStyle = "black";
242 cc.strokeRect( this.x, this.y, this.w, this.h );
243 };
244
245 function TextElement( x, y, text ) {
246 this.x = x ? x : 0;
247 this.y = y ? y : 0;
248 this.text = text ? text : "";
249 }
250 TextElement.prototype.draw = function( cc ) {
251 cc.fillStyle = this.color;
252 cc.strokeStyle = "black";
253 cc.font = "italic 32px 'MS Pゴシック'";
254 cc.fillText( this.text, this.x, this.y );
255 // cc.strokeRect( this.x, this.y, this.w, this.h );
256 };
257
258
259 //---以下 サンプル実行
260
261
262 function onloadx2() {
263
264 var blocktext = test.toString().match( /\{([\s\S]*)\}/ )[ 1 ];
265 instruction1 = new Instruction( null, null, null, blocktext, null );
266
267
268 var blocktext = test2.toString().match( /\{([\s\S]*)\}/ )[ 1 ];
269 instruction2 = new Instruction( null, null, null, blocktext, null );
270
271 // debugprint_recursive( instruction1 );
272 console.log( "-------------------------" );
273
274 a = 1;
275 b = 5;
276
277 instruction1.exec();
278 instruction2.exec();
279 }
280
281 function test() {
282 var b;
283 var c=b;
284 console.log( 1 );
285 if( a == (1+1)*2 || true ) {
286 b = 3;
287 if( false ) {}
288 } else {
289 b = 10;
290 }
291 mes = "スライムがあらわれた!";
292 for( var i = 0; i < mes.length; i++ ) {
293 console.log( mes.substr( i, 1 ) ); //anm200
294 }
295 if( true ) console.log(3);
296 function abc( x, y ) {
297 console.log(4);
298 }
299 abc( 1, 2 );
300 }
301 function test2() {
302 console.log( 123 ); //anm500
303 console.log( 1234 ); //anm500
304 console.log( 12345 );
305 }
306
307 //---以上 サンプル実行
308
309
310 </script>
311 <style>
312 </style>
313 </head>
314
315 <body onload="onloadx();" style="
316 background-color : lightgray;
317 ">
318 <canvas id="canvasELID" width="512" height="448" style="
319 display : block;
320 margin : auto;
321 background-color : white;
322 border : solid 1px black;
323 ">There is no canvas.</canvas>
324 </body>
325 <script src="batch.js"></script>
326 </html>