- ベストアンサー
画像が一瞬とぎれてしまう問題について
- フラッシュで画像を切り替えるアルバムを作っていますが、画像が切り替わる際に一瞬つなぎ目できれてしまいます。
- スクリプトの70フレームに、画像を読み込むためのコードを書いていますが、その際に画像が一瞬とぎれてしまう現象が発生します。
- 同じ画像を読み込んでも同様の問題が発生するため、他に解決策があれば教えていただきたいです。
- みんなの回答 (1)
- 専門家の回答
質問者が選んだベストアンサー
loadMovieでも MovieClipLoader の loadClip で画像を読み込む場合でも同じなのですが、ムービークリップで画像の読み込みが始まると、ムービークリップの一部の情報が初期化されます。 ムービークリップの内容(絵など)は初期化されて消去され、読み込みが終了するまでは真っ白な状態で表示されます。 つまり、同じムービークリップに繰り返し画像を読み込む限りは、たとえ同じ画像を読み込む場合であっても、真っ白になる瞬間が必ずできてしまいます。 「ムービープレビュー」では画像の読み込みに時間はかからないものの、それでも画像を読み込む時にムービークリップが真っ白になっている瞬間はあり、これがちらついたり点滅して見える原因です。 オンラインでは読み込みには更に時間がかかるのですから、ちらつくというよりは、読み込み中にしばらく画面が真っ白になってしまうことになるかと思います。 この空白を表示しないようにするには、要は、今表示しているムービークリップとは別のムービークリップに次の画像を読み込み、読み込んでいる間は前の画像をずっと表示しておけばいいのです。 ムービークリップを2つ用意して重ねて、下のムービークリップに画像を読み込み、読み込みが完了した時点でこちらのムービークリップを上にして表示する、という方法はいかがでしょう。 ムービークリップの重ね順は、swapDepths というメソッドで入れ替えることができます。 ---------------------------------------------------------- 多分ですが、No.1767152 の続きではないでしょうか。 読み込むファイル名を指定する方法は様々ですが、さしあたって、ファイルオープンエラーが出るまでファイルの番号をカウントアップしながら読み込む例を考えます。 また、読み込む画像は全て同じサイズであるものとして話を進めます。 画像を読み込むには、画像の受け皿となるムービークリップが必要です。 今回は2つのムービークリップに交互に読み込み、入れ替えながら表示します。ムービークリップを2つ、ステージに配置してください。 この2つは、ぴったり重ね合わせて配置します。 インスタンス名は都合により、固定の名前+ 0 または 1 で付けてください。ここでは仮に、clip0 と clip1 とします。 重ね順も大切で、clip0 の方が下になるように配置します。レイヤーを分け、clip0 を配置したレイヤーを下にすると簡単です。 ムービークリップに仮に画像のサイズの四角形などを描画した場合は、最初に、画像を読み込まないムービークリップの方のこれが表示されてしまいます。 2つのムービークリップにそれぞれ、 (↓各行頭に全角のスペースが入っています。コピーする際はご注意ください) onClipEvent(load) { //最初は非表示にしておく this._visible = false; } というスクリプトを設定しておくと、非表示になります。 なお、onClipEvent を使って設定したスクリプトは、ムービークリップに何かを読み込んだ後も初期化されずに残ります。 load イベントは画像等の読み込みが完了した時にも発生します。 従って、このスクリプトを書いたムービークリップに画像を読み込むと、読み込み完了と同時に画像が非表示になります。 MovieClipLoader はダウンロードの様々な段階でイベントを発生させて、状況を知らせてくれます。 しかし、これらのイベントはタイムラインから外れて発生する割り込み信号のようなものですから、タイムライン側で状況を把握しながら処理をするには少々工夫が必要です。 また、画像の読み込みにかかる時間は回線の速さや通信事情など、閲覧者の都合によっても変わってきます。”○フレーム後には読み込み終わるだろう”という勝手な推測のもとに次の処理に移ると、場合によって動いたり動かなかったりするなど、動作が不安定になる可能性があります。 そこで、変数(フラグといいます)を1つ用意し、イベントが発生する度にこのフラグを書き換えて、タイムラインに状況を知らせるようにします。 タイムラインではこの値を監視して状況を把握しながら、次の処理に進むことにします。 仮に load_status というフラグを用意したとして、値を次のように決めます。 0 :ファイルオープンを待つ 1 :読み込み中 2 :読み込み完了 -1:ファイルオープン失敗 MovieClipLoader の onLoadError を利用して、ファイルオープンに失敗した時、load_status に -1 を入れるようにします。 タイムライン側では load_status に -1 が入るまでは、ファイルの番号をカウントアップしながら画像を読み込み続けます。 これとは別に、今、画像を読み込む方のムービークリップの番号を管理する変数を1つ用意します。 ムービークリップには clip0 と clip1 という名前を付けましたので、この、0 か 1 かを変数で管理します。 仮にこの変数を clip_no としますと、画像を読み込むムービークリップは this[ "clip" + clip_no ] というようにして指定できます。 フレームに設定したアクションは、フレームに再生ヘッドがセットされた、その時1度しか実行されません。 いつか値が変わるフラグを監視して分岐させるスクリプトは、最初の1度しか実行されないようでは困ります。 再生ヘッドをセットし直せば、フレームアクションはその都度実行されるのですが、Flash は同じフレームに続けて再生ヘッドをセットすることはできない仕様になっています。 しかし、一旦前のフレームに再生ヘッドを戻してフレーム間をループさせると、フレームに設定したスクリプトを繰り返し実行させることができます。 この点から、フレームの構成は次のように考えます。 フレーム1:初期設定 フレーム2:画像の読み込み フレーム3:各処理の終了を待つためのフレーム。スクリプトは設定しない。 フレーム4:ファイルオープン/読み込み完了待ち、および読み込み終了後の処理など。 ---------------------------------------------------------- ステージにムービークリップ clip0 と clip1 があり、この2つは clip0 の上に clip1 が重なっているものとします。 フォルダ” pict ”にある画像ファイル(ファイル名は連番で付いているものとします)をあるだけ読み込むスクリプトは、大体、次のようになります。 このスクリプトはフレームに設定してください。 (↓各行頭に全角のスペースが入っています。コピーする際はご注意ください) ●フレーム1 //ファイルの管理番号を保持 m = 1; //読み込みの状況を管理 //0:ファイルオープン待ち 1:読み込み中 2:読み込み完了 -1:ファイル探しを終了 load_status = 0; //画像を読み込むムービークリップの番号を保持(0または1) clip_no = 0; //オブジェクトを作成 my_mcl = new MovieClipLoader(); prog = new Object(); /*ファイルオープン完了時の処理を定義*/ my_mcl.onLoadStart = function() { //ファイルオープン完了を知らせる load_status = 1; }; /*読み込み完了時の処理を定義*/ my_mcl.onLoadInit = function() { //読み込み完了を知らせる load_status = 2; }; /*エラー発生時の処理を定義*/ my_mcl.onLoadError = function( target:MovieClip , error_code:String ) { switch( error_code ) { //ファイルが見付からなかった場合: //ファイル探しの終了を知らせる case 'URLNotFound': load_status = -1; break; //ダウンロード失敗の場合: //とりあえず、何もしない case 'LoadNeverCompleted': break; default: break; } }; ●フレーム2 //画像の読み込み my_mcl.loadClip( "./pict/" + m + ".jpg" , this[ "clip" + clip_no ] ); ●フレーム4 /*読み込みの状況に応じて分岐*/ switch( load_status ) { //ファイルオープン完了待ちの場合: case 0: //オープン完了を待つ gotoAndPlay( _currentframe - 1 ); break; //読み込み中の場合: case 1: //進捗状況を取得 prog = my_mcl.getProgress( this[ "clip" + clip_no ] ); loaded = prog.bytesLoaded; total = prog.bytesTotal; progressmsg = loaded + " / " + total; //読み込み完了を待つ gotoAndPlay( _currentframe - 1 ); break; //読み込みが完了した場合: case 2: //読み込んだ画像を上に入れ替えて表示 this[ "clip" + clip_no ].swapDepths( this[ "clip" + ( ( clip_no + 1 ) & 1 ) ] ); this[ "clip" + clip_no ]._visible = true; //各情報を初期化し、次のファイルを探しに行く load_status = 0; m++; clip_no = ( clip_no + 1 ) & 1; gotoAndPlay( 2 ); break; //ファイルオープンに失敗した場合: case -1: //タイムラインはここで止める stop(); break; default: break; } 紙面の都合上、1つ1つを詳しくは説明できないのですが。 MovieClipLoader でイベントが発生した時、変数 load_status の値を書き換え、この値を監視することでタイムライン側で読み込みの状況を把握します。 エラーの原因には、指定のファイルが見付からなかった場合と、不測の理由でダウンロードが中断した場合の2通りが考えられます。 どちらのエラーが発生したのかは、onLoadError に渡されてくる第2引数で判別できます。今回は、ファイルが見付からなかった場合のみ load_status に -1 を入れ、ファイルがもうないものと見なしてファイル探しを打ち切るようにしています。 ちなみに MovieClipLoader は、あえてリスナーオブジェクトを登録しなくても、オブジェクトに直接イベント発生時の処理を定義することもできます。 ファイルオープンに成功し読み込みが始まった時、onLoadStart というイベントが発生します。 オンライン環境では特に、読み込みが始まるまで数フレームかかります。 OSや回線の状況などによっても読み込み開始にかかる時間が違います。読み込み開始を確認せずに完了率等を算出しようとすると、総容量・読み込み済み容量がともに 0 byte や undefined になることがあります。 上記のスクリプトでは、onLoadStart の発生を確認し、読み込みが確実に始まるのを待って進捗状況を把握するようにしています。 画像は、最初は clip0 に読み込み、読み込みが完了した時に swapDepths で clip1 と重ね順(深度)を入れ替え、clip0 を上にして表示します。 この時点で、clip1 が clip0 の下になります。 次の画像は clip1 に読み込み、同様に、読み込み完了時に clip0 と深度を入れ替えて上にします。 つまり、常に下のムービークリップに画像を読み込み、読み込みが済んだ時点で2枚の深度を入れ替えることで、画像が読み込まれるまでは前の画像を表示しておく仕組みです。 case 2: のところにある ( clip_no + 1 ) & 1 ↑この演算はちょっと馴染みのないものかもしれません。 詳しくは省略しますが、clip_no の値を 0 と 1 に限定するおまじないです。clip_no が 0 の時は 1 、1 の時は逆に 0 になります。 ムービークリップの名前を clip0 と clip1 と付けた理由も、実はここにあります。 MovieClipLoader で読み込んだ場合は、ダウンロードしたデータがハードディスクに書き込まれる度に発生する onLoadProgress イベントか、getProgress というメソッドを利用して進捗状況を把握できます。 onLoadProgress イベントはオフラインでは発生しないので、getProgress がオススメです。 getProgress は戻り値が2つあります。値の取得方法にはご注意ください。 汎用型である Object 型の変数を用意し、2つをまとめて受け取ります。 この作例では、読み込みが終了次第、次の画像を読み込んで表示します。 「ムービープレビュー」ではダウンロードにかかる時間が考慮されないため、あっという間に画像が更新されていってしまいますし、getProgress も上手く動作しませんが、これは正常です。 「ムービープレビュー」で「表示」→「ダウンロードのシミュレート」にチェックを入れて、確認してみてください。 長くなってすみませんでした。
お礼
ありがとうございました。 結局、違うタイムラインで途切れるすこしまえに読み込んでおく方法で解決いたしました。今回のご回答も参考にさせていただきました。 いつもありがとうございます。