- ベストアンサー
Flash:外部JPEG読み込み待ちについて
- Flash MX2004を使用して、外部JPEGを4枚読み込ませる方法を教えてください。
- 読み込むJPEGファイルはサイズが小さく、一般的な回線速度でも再生に追いつかないことはありませんが、全ての画像を読み込み終わるまで再生しない方法を知りたいです。
- ActionScriptは初心者であり、サンプルコードの修正程度の知識しかありません。どなたか教えていただけないでしょうか。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
JPEG 画像を読み込むには、loadMovie の他に、Flash MX 2004 から登場した MovieClipLoader クラスを使う方法があります。 loadMovie は古いバージョンの Flash Player でも動く利点があります。 しかし、loadMovie による読み込みの進捗状況は getBytesLoaded と getBytesTotal で把握できることはできるのですが、実行するタイミングによっては画像を読み込むために用意したムービークリップインスタンス自体の容量が返ってくる場合があり、loadMovie で画像を読み込む際の進捗状況が正確に把握できないことがあるようです。 Flash MX 2004 をお使いとのことですので、ここでは、MovieClipLoader を使った作例をご紹介します。 外部から何かのデータを読む時は、少なからず時間がかかるものです。 読み込みが終わるまで待ってから先に進むといった処理は、1つのフレームやオブジェクトアクションだけで何とかしようとしないで、フレーム間をループする発想で考えると作りやすいです。 フレームの構成は、次のように考えます。 フレーム1:初期設定と読み込み開始。 フレーム2:読み込み完了を待つためのフレーム。スクリプトは設定しません。 フレーム3:読み込み完了判定と完了率の算出・読み込み完了後の処理など。 フレーム4:タイムラインを止め、普段はここを表示します。 レイヤーは次のような構成にします。 アクション:スクリプトを書きます。 完了率表示:完了率を表示します。 クリップ :画像を読み込むためのムービークリップを配置します。 読み込みが終了したら、フレーム4でタイムラインを止めます。続くアニメ等があるようでしたら、止めずに先に進んでください。 完了率はフレーム1~3まで表示します。 仮に、ステージにムービークリップ ph01 ~ ph04 があり、それぞれに 01.jpg ~ 04.jpg を読み込むものとします。 また、完了率をプログレスバーで表示するために、ムービークリップのインスタンス prog_bar が配置されているものとします。 スクリプトはフレーム1と3に書きます。 各フレームのスクリプトは、大体、次のようになります。 (↓各行頭に全角のスペースが入っています。コピーする際は、全て半角のスペースかタブに置き換えてください。このまま使うとシンタックスエラーになります) ●フレーム1 //読み込み用オブジェクトの作成 load_obj = new MovieClipLoader(); //完了率算出用オブジェクトの作成 prog = new Object(); //読み込みが完了したファイル数を保持 loaded_cnt = 0; //画像の総数を保持 image_max = 4; //プログレスバーが見えないようにする prog_bar._xscale = 0; /*読み込み終了時の処理を定義*/ load_obj.onLoadInit = function( clip:MovieClip ) { //一旦、画像を非表示にしておく clip._visible = false; //読み込みが完了した総数を更新 loaded_cnt++; }; /*エラー発生時の処理を定義*/ load_obj.onLoadError = function() { //何らかのトラブルで読み込みが失敗した場合も、 //さしあたって読み込みが終了したものと見なす loaded_cnt++; }; //画像を読み込む for( i = 1 ; i <= image_max ; i++ ) { load_obj.loadClip( "0" + i + ".jpg" , this[ "ph0" + i ] ); } ●フレーム3 //全ての画像が読み込み終わるまで待つ if( loaded_cnt < image_max ) { //読み込み完了率を算出 loaded = 0; total = 0; for( i = 1 ; i <= image_max ; i++ ) { //進捗状況を取得 prog = load_obj.getProgress( this[ "ph0" + i ] ); //全画像の合算で完了率を出す loaded += prog.bytesLoaded; total += prog.bytesTotal; per = Math.floor( loaded / total * 100 ); } //プログレスバーの描画 prog_bar._xscale = per; //読み込み完了まで待つ gotoAndPlay( _currentframe - 1 ); } else { //全て読み込まれたら、全画像を表示 for( i = 1 ; i <= image_max ; i++ ) { this[ "ph0" + i ]._visible = true; } //次のフレームでタイムラインを止める nextFrame(); } MovieClipLoader は画像や swf ファイルの読み込みを専門に請け負うクラスです。 loadMovie よりも多くのイベントが発生し、進捗状況を細かく把握することができます。 MovieClipLoader では1つのオブジェクトで複数の読み込みを管理でき、1度イベント発生時の処理を定義しておくと、どの読み込みでイベントが起きた時も同様の処理を行ってくれます。 今回は、読み込みが完了した時に発生する onLoadInit と、商業用の作品のご様子でしたので、エラー時に発生する onLoadError イベントを利用しています。 まず、読み込み完了時の指示である onLoadInit についてですが。 今回は4枚の画像を、1つの MovieClipLoader クラスのオブジェクト(上記の例では load_obj )で読み込みます。 MovieClipLoader では1件1件の読み込みごとにイベントが起きますが、4枚とも全て終わったかどうかは、スクリプトを工夫しないと判断できません。 そこで、1件の読み込みが済むごとにカウントをとり、これが画像の総数と一致しているかどうかで、4件の読み込みが済んだかどうかを判断するものとします。 完了率は4枚分の合算で求めますから、完了率が 100 %に達したかどうかでも、理論的には終了を判断できます。 しかし、もし読み込みが途中で失敗した時には計算が狂ってしまいますし、実は MovieClipLoader で読み込んでも、getProgress を実行するタイミングによっては総容量とロード済み容量がともに0になっていたり未定義になっていたりすることがあり、上手くいかない場合があります。 このあたりはどうも、回線の都合等で読み込みが始まるタイミングが違うことが原因のようです。 完了した件数のカウントで判断すれば、総容量とロード済み容量が取得できない状況で0が返ってきたとしても、それは一時的な現象で、ファイルが開かれれば次からは正常な値を取得でき、より確実に完了を検出できます。 画像を複数読み込むと、通常は、読み込みの済んだものから順次表示されていきます。 今回は完了率をプログレスバーで表示しているので、途中で画像が重なって表示されてしまっては困ります。 上記のスクリプトでは、onLoadInit の中で、読み込み完了と同時に画像を一旦非表示にして、4枚とも読み込み終わるのを待ってから、全画像を表示するようにしています。 画像は容量が大きく読み込み時間も長くなるため、途中で回線が切断したりサーバーのトラブルなど、不測の理由によりダウンロードが失敗する可能性があります。 onLoadError は、エラーでダウンロードが失敗した時に発生するイベントです。 今回は省略していますが、エラーが起きたムービークリップと、エラーの種類( URL が見付からなかったためか、もしくは回線の切断等によるダウンロードの未完了)を判別することもできます。 今回は、エラーで中断したものはとりあえず読み込み終了と見なして、単純に終了した数を更新しているだけですが、再度読み直したり、ブラウザでいうところの×印などを表示しておくといった処理にも利用できます。 エラー処理につきましては、ヘルプのサンプルをご参考になさってください。 MovieClipLoader で読み込んだ場合は、getProgress という命令(メソッドといいます)で進捗状況を把握できます。 getProgress の戻り値は総容量とロード済み容量の2つですので、汎用型の Object 型の変数を作り、まとめて受け取ります。 上記のスクリプトでは、変数 per に4件分の完了率がパーセントで入ります。 さしあたってプログレスバーの描画に利用していますが、ダイナミックテキストで表示すると、Now Loading ○%というスタイルでも表示できます。 長くなってすみませんでした。 不明な点がありましたら、補足してください。
その他の回答 (1)
- DPE
- ベストアンサー率85% (666/776)
01.jpg ~ 04.jpg を、ムービークリップ ph01 ~ 04 と ph05 ~ 08 に読み込む、ということですね。 for ループを二重にすることで、対応できます。 画像は4種類ですが、ムービークリップは倍の8つになります。 必要な時に計算で image_max * 2 としてもいいのですが、この数は何回か利用するので、変数として持っておくと便利です。 フレーム1に、次のようなスクリプトを追加してください。 場所はどこでも構いませんけれど、image_max = 4; の次あたりが分かりやすいと思います。 //画像を読み込むムービークリップの総数を保持 //(同じ画像を2組ずつ読み込む) clip_max = image_max * 2; それから、フレーム1の画像を読み込む for ループを次のように変更します。 //画像の読み込み //同じ画像を2組読み込む for( i = 0 ; i < 2 ; i++ ) { for( j = 1 ; j <= image_max ; j++ ) { clip_no = ( i * image_max ) + j; load_obj.loadClip( "0" + j + ".jpg" , this[ "ph0" + clip_no ] ); } } 画像の番号は1~4が2回に対し、ムービークリップの番号は1~8と参照できるようにループを考えます。 画像の方は1~4を2回出すだけですから、2回繰り返す i のループの中に1~4までの間繰り返す j のループを組み込むことでクリアできます。 ムービークリップの番号を、i と j の値を使って1~8と出るように求める式が、少々工夫が必要とされるところです。 内側にある j のループでは、j が1~4の間、ループが継続します。 ムービークリップの番号は、1回目のループでは1~4でいいので、j の値に何も加算せず、そのまま利用できます。 しかし、2回目は5~8で、これは、 j の値に画像の枚数(= image_max )の分だけ加算した値といえます。 従って、ムービークリップの番号は 画像の枚数× ( ループ回数 - 1 ) + j で、求められます。 ループの回数は、この場合は外側のループのループカウンタ i のことです。i の初期値を0から始めると、-1 する手間を省いてスッキリとループを組むことができます。 今回は2組ですが、i のカウントを増やすと、3組でも4組でも同様に読み込めます。 ムービークリップが増えた分、フレーム3で完了を検出する部分にも変更が必要です。 ムービークリップの総数は clip_max という変数に入れています。フレーム3のスクリプトで image_max としていた部分を、全て clip_max に変更してください。 フレーム3のスクリプトの冒頭にある if 文の条件内と、2箇所ある for ループの、3箇所で使っています。 -------------------------------------------------------- ところで、ムービークリップが8つもあると、読み込みの都合上、スクリプトが実行される時にはまだムービークリップが読み込まれておらず、ムービークリップが undefined (未定義)になっているために画像の読み込みが失敗することがあります。 速度の遅い回線で閲覧する場合は特に、スクリプトに落ち度がなくても、このような理由から画像が表示されないトラブルが発生する可能性もあります。 フレーム1の前に空のフレームを1つ挿入し、ムービークリップよりも後で読み込みのスクリプトが実行されるようにしておくと、万全だと思います。
お礼
DPE様、丁寧なご回答本当にありがとうございます! 少し手間取りましたが、無事完成し大満足のものが出来ました。 大変感謝しております。ありがとうございました。
補足
早々のご回答ありがとうございます! 上記のスクリプトを試してみたところ、何とかなりそうです。本当に助かりました。ありがとうございました! ただ、先に書いておけば良かったのですがもう一つ問題があります。 実は同じJPEGファイルを二回ずつ読み込みたいのです。 一つは普通に表示し、もう一つはその背面でフェードインしながら大きくなる→フェードアウトといった動きをつけます。 その為、前までは this.ph01.loadMovie("01.jpg"); this.ph02.loadMovie("02.jpg"); this.ph03.loadMovie("03.jpg"); this.ph04.loadMovie("04.jpg"); this.ph05.loadMovie("01.jpg"); this.ph06.loadMovie("02.jpg"); this.ph07.loadMovie("03.jpg"); this.ph08.loadMovie("04.jpg"); といった具合に読み込ませていました。 (読み込む量が二倍になってしまうし、スマートじゃないのですが・・) 教えて頂いたスクリプトでは、読み込むファイルの名前を "0" + i + ".jpg" , this[ "ph0" + i という形で表しているのですよね。 この場合、同じファイルを二度読み込む方法はありますでしょうか。 素人臭い質問で申し訳ありません。 どうかよろしくお願い致します。