Skin: [NORMAL]
[BLUE]
[DOS] [LIGHT]  / コピーするための表示 / 実行
このファイル: /home/web6047/www/cgi-bin/prj/20180728-javascript/callbackを使った例(合理anmからcallback)/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 elements = new Object();
35 elements.A = new Element( 50, 300, null, null, "red" );
36 elements.B = new Element( 500, 300, null, null, "green" );
37 elements.C = new Element( 250, 300, null, null, "blue" );
38
39
40 //アニメエンジン始動
41 anms = new Array();
42 timerMS = 100;
43 timerID = setInterval( run, timerMS );
44
45
46 //アニメの作成
47 anm = new Anm( timerMS, 2000, function() { console.log( "callback" ) } );
48
49 //●3 関数での移動ができている。
50
51 //どのように移動するかを定義する関数
52
53 //放物線 関数
54 f1 = function() {
55 var cnt = this.parent.cnt;
56 var cntmax = this.parent.cntmax;
57
58 var x = cnt / cntmax; //0~1
59 x -= .5;
60
61 var y = x * x * 1000;
62
63 return y;
64 }
65
66 //正弦波 関数
67 f2 = function() {
68 var cnt = this.parent.cnt;
69 var cntmax = this.parent.cntmax;
70
71 var y = Math.sin( cnt ) * 20;
72
73 return y;
74 }
75
76 //各動き
77 anm.add( elements.A, "x", elements.A.x, elements.C.x );
78 anm.add( elements.A, "y", elements.A.y, elements.C.y, f1 );
79 anm.add( elements.B, "x", elements.B.x, elements.C.x );
80 anm.add( elements.B, "y", elements.B.y, elements.C.y, f2 );
81 anm.reverse = true;
82 anms.push( anm );
83
84
85 //背景色アニメ
86 anm = new Anm( timerMS, 3000 );
87
88 //新しい背景色を返す関数
89 f3 = function() {
90 var cnt = this.parent.cnt;
91 var cntmax = this.parent.cntmax;
92
93 var val = 255 * ( cnt / cntmax );
94
95 return "RGB(" + val + "," + val + "," + val + ")";
96 }
97
98 anm.add( document.body.style, "backgroundColor", 0, 255, f3 );
99 anm.reverse = true;
100 anms.push( anm );
101
102 }
103 function run() {
104 var drawFLG = false;
105
106 //アニメ実行
107 for( var i = 0; i < anms.length; i++ ) {
108 var anm = anms[ i ];
109
110 //check. アニメの終了検知
111 if( anm.reverse ) {
112 if( anm.direction > 0 && anm.cnt > anm.cntmax ) {
113 anm.direction *= -1;
114 anm.cnt = anm.cntmax - 1;
115 } else if( anm.direction < 0 && anm.cnt < 0 ) {
116 anm.direction *= -1;
117 anm.cnt = 1;
118 }
119 } else if( anm.cnt > anm.cntmax ) {
120
121 //●2 一連のアニメの終了でcallbackが実行できている。 大きな目的。
122
123 anms.splice( i--, 1 ); //アニメ削除
124 anm.callback(); //アニメ後処理
125 continue;
126 }
127
128 //アニメanmが含む各動きmotionについて
129 for( var j = 0; j < anm.motions.length; j++ ) {
130
131 var motion = anm.motions[ j ];
132
133 if( motion.isNum ) {//変更する値が数値である場合
134
135 if( motion.f )
136 motion.element[ motion.member ] = motion.sx + motion.f() - motion.firstF; //←関数はここで実行
137 else //単純な移動 始点から目的地までの距離*進捗
138 motion.element[ motion.member ] = motion.sx + motion.length * ( anm.cnt / anm.cntmax );
139
140 } else //変更する値が文字列である場合( たとえば、"RGB(255,255,255)" など )
141 motion.element[ motion.member ] = motion.f();
142
143 }//for j
144
145 anm.cnt += anm.direction;
146 drawFLG = true;
147
148 }//for i
149
150 if( drawFLG ) draw( canvas );
151 }
152 function draw( cc ) {
153 cc.clearRect( 0, 0, screenW, screenH );
154 //画面要素を描く(赤、青、緑の四角)
155 for( var name in elements ) {
156 var element = elements[ name ];
157 element.draw( cc );
158 }
159 }
160
161
162 //---クラス アニメオブジェクト
163
164 function Anm( timerMS, ms, callback ) {
165 //●1 一連のアニメを合理的にAnmにまとめている。 大きな目的。
166
167 //ひとつのアニメオブジェクトに cnt, cntmax が1組あり、
168 this.cnt = 0;
169 this.cntmax = Math.floor( ms / timerMS );
170
171 //ひとつのアニメオブジェクトに複数の動き motions があるところが、合理的。
172 this.motions = new Array();
173 this.callback = callback ? callback : function() {};
174
175 /*
176 つまり、このようにすれば、
177 複数の動きを同じ時間に開始し、終了し、終了したら callback を1回実行する
178 ということがやりやすくなる。
179
180 これをSVC(Side View Character)に例えると、あるポーズから別のポーズへ3秒で変更する場合、
181 全ての関節を3秒で回転させ、回転完了して別のポーズになったら callback を1回実行する。
182 ということがやりやすくなる。
183
184 この callback を1回実行するというのは、自作のJavaScriptエンジンからSVCのポーズアニメを実行したとき、
185 アニメの完了でcallbackを使ってエンジンへ戻る、という用途を想定している。
186 */
187
188 this.repeat = false;
189 this.reverse = false;
190 this.direction = 1;
191 }
192 Anm.prototype.add = function( element, member, sx, ex, f ) {
193
194 var motion = {
195 element : element,
196 member : member,
197 sx : sx,
198 ex : ex,
199 length : ex - sx,
200 parent : this,
201 f : f,
202 firstF : 0,
203 isNum : element[ member ].match ? false : true,
204 };
205
206 //関数を使う場合の位置合わせの値 firstF について
207 if( f ) {
208 motion.firstF = motion.f();
209 }
210
211 this.motions.push( motion );
212 };
213
214
215 //---クラス 画面要素オブジェクト
216
217 function Element( x, y, w, h, color ) {
218 this.x = x ? x : 0;
219 this.y = y ? y : 0;
220 this.w = w ? w : 24;
221 this.h = h ? h : 24;
222 this.color = color ? color : "black";
223 }
224 Element.prototype.draw = function( cc ) {
225 cc.fillStyle = this.color;
226 cc.fillRect( this.x, this.y, this.w, this.h );
227 cc.strokeStyle = "black";
228 cc.strokeRect( this.x, this.y, this.w, this.h );
229 };
230
231
232 </script>
233 <style>
234 </style>
235 </head>
236
237 <body onload="onloadx();" style="
238 background-color : lightgray;
239 ">
240 <canvas id="canvasELID" width="512" height="448" style="
241 display : block;
242 margin : auto;
243 background-color : white;
244 border : solid 1px black;
245 ">There is no canvas.</canvas>
246 </body>
247 </html>