- ベストアンサー
ルートとムービークリップの関係について
- ルートとムービークリップの関係について説明します。ターゲットとは、外部のJPEGファイルを読み込むためのダミーのムービーです。
- スクロールバーを使用してシート内のムービークリップを横展開する方法も説明します。
- しかし、JPEGファイルの表示範囲はマスク内のみであり、スクロールしても画像自体は動きません。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
#3で、Flash MX の ScrollBar コンポーネントは setScrollProperties を実行しなくてもスライダが表示されると書いてしまいましたが、MX 2004 の UIScrollBar コンポーネントと同様、setScrollProperties を実行するまではスライダが表示されないようです。 少々勘違いをしてしまい、大変失礼をいたしました。この場を借りて、訂正させていただきます。 ・・・ところで、setChangeHandler を使っているということは、引き続き MX の ScrollBar コンポーネントをご利用されていると解釈して、よろしいのでしょうか? Flash Exchange で配付されている MX のコンポーネントのセットにある ScrollBar コンポーネントと、アップデータ 7.2 で復活した UIScrollBar は別のものですので、どちらを使うかによって、スクリプトも変わってきますが。
その他の回答 (3)
- DPE
- ベストアンサー率85% (666/776)
Flash MX 2004 のアップデータ 7.2 で復活した UIScrollBar コンポーネントに入れ替えたのであれば、Sheet_Scrolling 関数と setChangeHandler は不要です。まあ、Sheet_Scrolling 関数を作り、スクロールバーが動いた時に実行される on アクションの中で呼んでも構わないのですが。 関数を使う場合は、Thumb_nail のタイムラインのフレーム1に、 function Sheet_Scrolling() { sheet._x = sc_bar.scrollPosition * ( -1 ) + 50; } と定義します。初期設定の最初でも最後でも構いません。 UIScrollBar のインスタンス sc_bar を選び、オブジェクトアクション(ムービークリップやボタンのインスタンスに設定する時と同じ要領)として on(scroll) { _parent.Sheet_Scrolling(); } というアクションを設定してください。 Sheet_Scrolling 関数を所有しているのは Thumb_nail で、sc_bar から見ると親にあたります。親の持つ関数ですから、sc_bar からその関数を呼ぶためには、親までのターゲットパスが必要になります。 Sheet_Scrolling 関数を削除して、 on(scroll) { _parent.sheet._x = this.scrollPosition * ( -1 ) + 50; } としても、同じことです。 関数を使う場合と on の中で sheet を動かす場合とでは、ターゲットパスが違います。パスの間違いにご注意ください。 ムービークリップやボタンがクリックされた時の処理で、ムービークリップやボタンのインスタンスに設定するオブジェクトアクションとして、 on(press) { ・・・ } このようなアクションが使えます。 press や release などの文字列を、イベントハンドラと言います。ムービークリップやボタンに何が起こった時(イベントが発生した時)にスクリプトを実行するのかを、指示するためのものです。例えば press はクリックされた時、release はクリックしてマウスボタンが離された時に発生するイベントです。 UIScrollBar は、scroll という独特のイベントハンドラを持っています。このイベントは、スライダが動くと発生します。 Flash MX の ScrollBar コンポーネントには、このイベントハンドラがありませんでした。それに代わるものとして、事前に関数を登録しておくと、スライダが動いた時に自動的にその関数を呼び出してくれるという機能があったのです。 また、UIScrollBar コンポーネントでは、getScrollPosition というメソッドが廃止されました。スライダの位置が scrollPosition というプロパティになり、参照するのも書き換えるのも簡単になりました。ムービークリップで位置を参照したり書き換えたりする時に、sheet._x = ・・・と書くのと、同じ要領です。 スクロールバーの範囲を決める setScrollProperties は、今回は画像の読み込みが終わるまでは、特に第3引数が決定できません。 従って、画像の読み込みが終わった時に実行することになります。 画像の読み込みは e_flg が -1 かどうかで判断していると思いますので、switch 文の case -1: の時に実行して、いいと思いますよ。 MX の ScrollBar コンポーネントでは、setScrollProperties を実行しなくてもスライダが表示されていましたが、MX 2004 の UIScrollBar コンポーネントでは、setScrollProperties を実行するまではスライダが表示されなくなりました。 画像の読み込みが終了した時点で setScrollProperties を実行すれば、読み込みが終わるまで画像のスクロールができなくなるので、スクロールバーの有効・無効を決める enabled の操作も不要になります。
- DPE
- ベストアンサー率85% (666/776)
要するに、 ・Thumb_nail ┗スクロールバー( sc_ bar ) ┗ sheet ┗画像読み込み用ダミー( target ) という構成のムービークリップで、sheet の子である target を複製しながら、そこに画像が読み込めればいいわけですよね。 ActionScript は、変数・関数・インスタンスが存在する位置(階層)にうるさい言語です。階層の指定が間違っていると、エラーにはならないものの期待した通りに動作しませんし、参照する時には、いちいち、目的のものがどこの階層にあるかを考えなければなりません。 しかし、同じ名前でも、例えば _root にある target と sheet にある target は別のものになります。そのため、同じシンボルから作られた複数のインスタンスが同じ名前の変数を持っていたとしても、きちんと区別がつきます。 また、位置(ターゲットパス)さえ適切に指定すれば、どの階層からも、他の階層が持っている変数等を参照できます。このルールは、変数や関数・インスタンス全てに共通するものです。 階層の考え方やパスの指定は、ActionScript では大きな意味を持っています。解説書等でしっかり研究してください。 それで、Thumb_nail ムービークリップに話は戻りますが。 Thumb_nail のタイムラインから、sheet の子である target を複製して、そこに画像を読み込むには、 sheet.target.duplicateMovieClip( "b" + i , i ); this[ "sheet" ][ "b" + i ].loadMovie( "b" + i + ".jpg" ); と、target までのパスを指定すると、Thumb_nail のタイムラインにスクリプトを書いても、その子 sheet の更に子になっている target を参照することができます。 文字列を使ってインスタンスや変数などにアクセスするには、eval か配列演算子 [ ] を使います。 [ ] の場合は、1階層分の文字列につき1組の [ ] を用意します。 [ "sheet.b" + i ] では正常に動作しませんので、ご注意を。この場合は this を省略して、sheet[ "b" + i ]と書くこともできます。 画像の場合は特に、読み込みにかかる時間を考慮しましょう。 画像はテキストファイルとは違い、どんなに小さい画像でもそれなりに容量があり、読み込みには時間がかかるものです。 (どのくらい時間がかかるかは、「ムービープレビュー」→「表示」→「ダウンロードのシミュレート」で確認してください) 従って、読み込みが終わるまで待つ処理が必要になります。この処理は、フレーム間をループして作るのが簡単です。 フレームをまたいだループでは、for のループは使えません。 代わりにフラグを使い、フラグが立つまでフレーム間をループするようにします。このループは、以前、テキストファイルの読み込みでもご紹介しました。http://okweb.jp/kotaeru.php3?q=961443 を参考に、改良してみてください。 先述の通り、Thumb_nail のタイムラインからでも、 sheet の子の target を操作することは可能です。Thumb_nail のタイムラインで画像を読み込み、フラグも Thumb_nail に用意して Thumb_nail のフレームでループしながら完了を待つ方が、スクリプトが1箇所にまとまり、また、変数のターゲットパスも複雑にならず、管理もしやすいと思いますよ。 ------------------ 例えば、ムービークリップがクリックされた場合に何かをさせたい場合、 target.onPress = function ()・・・ と、定義しておくことができます。 この関数は、いつ実行される(呼び出される)と思いますか? フレーム1でこのように定義しても、その時点でムービークリップがクリックされなければ関数は呼び出されません。 しかし、例えば target がフレーム1~10 まで存在していて、フレーム 10 でクリックされたとしても、この関数は呼び出されます。関数の定義されているフレームが、たとえフレーム1だったとしてもです。 スクロールバーの関数も、この仕組みとよく似ています。 フレーム1で Sheet_Scrolling 関数を定義しても、この関数を呼び出さなければ実行されません。 では、この関数はいつ呼び出すのかと言いますと。 予め、sc_bar のスライダが動いた時は Sheet_Scrolling という関数を自動的に呼ぶようにと、約束しておきます。 その約束を交わすのが、setChangeHandler です。ムービークリップでいうところの、onPress = function ・・・と同じようなものと考えてください。 自動的に呼ぶ関数を1度登録さえしておけば、スライダが動くたびに自動的に Sheet_Scrolling 関数が呼び出されます。 ScrollPane もどきでは、フレーム1で Sheet_Scrolling 関数の実体だけ定義して、実際に関数を呼び出しているところはなかったはずです。それでも、スライダが動くと画像が動く= Sheet_Scrolling 関数が呼び出されているのは、フレーム1の setChangeHandler で関数を登録しているので、あとはスライダが動くたびに自動で呼び出されていたためです。 つまり、setChangeHandler と Sheet_Scrolling 関数は、フレーム1に設定しても構いません。ただし、フレーム1で既に、スクロールバーや sheet がタイムラインに存在していることが条件です。 今回は読み込んだ画像の数によって sheet の長さが変わり、それに伴い、スクロールバーの範囲も変化します。 ですから、スクロールバーの範囲を決める setScrollProperties は逆に、画像の読み込みが終わるまでは値が決められないということになります。 sc_bar.enabled = false; とするとスクロールバーが無効になり、スライダの操作ができなくなります。読み込みが終わるまで無効にしておき、読み込みが済んだ時点で スクロールバーを有効( sc_bar.enabled = true )にすると、読み込み中にスライダを動かされて sheet の位置がズレてしまうような事態も、防ぐことができます。 ここでは詳しくは書けませんが・・・ Flash MX 2004( Flash Player 7 )から使えるようになった、MovieClipLoader というクラスがあります。 swf や JPEG ファイルの読み込みに主眼を置いたクラスで、loadMovie や LoadVars よりも更に細かいダウンロードの進行状況を把握できます。 LoadVars で一旦画像を読んでから、もう1度loadMovie で読み直すと、ダウンロードにかかる時間は2倍になってしまいます。また、1つの読み込みが済んでから次を読んでいたのでは、効率も悪いです。 スクリプトは難しくなりますが、ファイルが存在するだけ読み込み、しかも複数のファイルを並行して読み込むというような芸当も、MovieClipLoader を使うと実現できます。 この話はまた長くなりますので、別の機会に。
お礼
先程の補足の補足ですが、thumb_nail内の1フレームにscritpを下記のようにしました。 (正しい位置でScrollBarも正しく動きます) var i = 1 ; var e_flg = 0 ; function Sheet_Scrolling() { sheet._x = sc_bar.getScrollPosition()*(-1) + 0 ; } sc_bar.setScrollProperties(50, 0, 720); sc_bar.setChangeHandler("Sheet_Scrolling"); 横90Pixcelの画像が12枚、マスクの幅が360Pixcelと分かっていたので移動最大値を720と設定しましたが、これを(画像を読み込んだ枚数*90-360)としたいのです。 普通に考えれば、読み込んだ枚数は「i」の内容から1を差し引いたものですので、「(i - 1) * 90 - 360」で算出される筈です。 でも、 sc_bar.setScrollProperties(50, 0, (i - 1) * 90 - 360) ; こうすると、ScrollBarは現れなくなります。 上記のScriptはどこで動かせば宜しいのでしょうか?。 やはり、ファイルの存在を判定している箇所でファイルが無くなった時に設定するのが普通のやり方なのでしょうか?。
補足
Thumb_nailインスタンス配下に ・script ・scroll ・mask ・image こんなレイヤーを配置しました。 1フレームのアクションには <初期処理> var i = 1 ; var e_flg = 0 ; 3フレームのアクションには <データ読込み処理> var fileload:LoadVars = new LoadVars(); fileload.load("b"+i+".jpg"); fileload.onLoad = function(success:Boolean) { if (!success) { e_flg = -1; } else { e_flg = 1 ; } }; 5フレームのアクションには <判定処理> switch(e_flg ) { case 0 : gotoAndPlay(4) ; break ; case 1 : sheet.target.duplicateMovieClip("b" + i, i) ; sheet["b" +i].loadMovie("b" + i+ ".jpg") ; sheet["b" +i]._x += (i - 1) * 90 ; i++ ; e_flg = 0 ; gotoAndplay(3) ; break ; case -1: sc_bar.setScrollProperties(50, 0, (i-1)*90-360); stop() ; break; default: break ; } こんなふうにしました。 下記の関数はThumb_nail内の1フレームの初期処理の下方に記述すれば良いと言う事ですが、 function Sheet_Scrolling() { sheet._x = sc_bar.getScrollPosition()*(-1) + 50 ; } このステートメントはどこに記述すれば良いのでしょうか?。 sc_bar.setScrollProperties(50, 0, (i - 1) * 90 - 360); 確か、setChangeHandlerは無くなったんですよね。
- DPE
- ベストアンサー率85% (666/776)
http://okweb.jp/kotaeru.php3?q=974758 で紹介しました、” ScrollPane もどき”の続きでしょうか? ” ScrollPane もどき”はムービークリップシンボルで、アクションも全て1つのシンボルの中にあります。構成は次のようになっています。 ・ScrollPane もどき ┗スクロールバー( sc_bar ) ┗ sheet ┗画像 ステージに ScrollPane もどきのインスタンスを置き、thumb_nail とインスタンス名を付けると、sheet までの絶対パスは _root.thumb_nail.sheet となります。 (ちなみに、パスは、階層の区切りを表す”.”を”~の”と読み替えると分かりやすいかと思います。_root の thumb_nail の sheet 、という具合です) 相対パスで指定する時は、スクリプトがある階層までのパスは省略できます。 ScrollPane もどきでは、制御のスクリプトを全て、ScrollPane もどきのタイムラインに設定していました。_root.thumb_nail までのパスが省略可能ですから、ScrollPane もどきのタイムラインから sheet を見た時は、単に sheet となります。sheet と同じ階層にある sc_bar も同様です。 では、対等の階層である sheet と sc_bar の間ではどうなるでしょうか? 例えば sc_bar から sheet を見ると、sheet は自分の親( thumb_nail )の子であるといえます。 子から親のタイムラインを参照するには、_parent を使います。従って、sc_bar から sheet の相対パスは、_parent.sheet となります。 ご質問文から察するに、今回は _root ┗スクロールバー( sc_bar ) ┗ sheet ┗画像( target ) という階層になっていて、スクリプトは主に sheet のタイムラインで設定していらっしゃるのだと思います。 ここで1つ問題になるのは、スクロールバーが動いた時に呼ぶ関数を登録する setChangeHandler です。 このメソッドは、正式には引数が2つになっています。第1引数が関数名、第2引数は、スクロールバーがあるタイムラインから見た、関数が定義されている階層までのパスで、省略した時はスクロールバーがあるタイムライン(スクロールバーの親タイムライン)になります。 前回紹介した ScrollPane もどきでは、Sheet_Scrolling 関数は ScrollPane もどきのタイムラインにありました。つまり、スクロールバー sc_bar から見ると、親にあたるタイムラインです。ですから、省略が可能でした。 今回は、sc_bar は _root に、登録したい関数は親の別の子のタイムラインにあります。ですから、第2引数で、_root から見た sheet のタイムラインまでのパスを指定する必要があります。 また、sheet で定義した関数で sheet._x = ・・・とした場合、sheet の中の sheet というインスタンスを操作するという意味になります。 sheet で定義した関数の中で自分自身を動かしたい場合は、自分自身を指す this を使うか、パスを省略して、単に _x = ・・・とします。 ・・・理論上は、絶対でも相対でもパスさえ正しければ、どこで定義しようがどのインスタンスであろうが操作はできるのですが、スクリプトの管理面から見ると、それが分かりやすい書き方であるとは限りません。 _root にあるスクロールバーに関係のある関数なら、わざわざ sheet で定義しなくても、_root のタイムラインで定義した方が簡単です。 また、sheet は _root の子です。_root にある関数から sheet を動かす場合は sheet._x = ・・・となり、関数も直さなくて済みます。 それから、setChangeHandler は _root のフレーム1で実行されており、登録する Sheet_Scrolling 関数は sheet のフレーム5で定義しているとのことですが。 setChangeHandler で登録しようとしている関数は、 setChangeHandler が実行された時には、まだ存在していません。従って、実は階層の間違い以前の問題だと思います。 -------------------- ところで、MX 2004 のアップデータ 7.2 では、廃止されていた ScrollBar コンポーネントが、より使いやすくなって帰ってきました。 MX の ScrollBar コンポーネントとは一部の仕様が変更され、名前も UIScrollBar と変わっています。 まず、今回の問題になった setChangeHandler がなくなりました。代わりに scroll というイベントハンドラが設けられ、ボタンやムービークリップと同じ感覚で利用できます。 また、スライダの位置が scrollPosition というプロパティになり、位置を参照したり書き換えたりするのも簡単になりました。 ( MX の ScrollBar では、getScrollPosition・setScrollPosition というメソッドを介して参照・書き換えます) つまり、 on(scroll) { _root.sheet._x = this.scrollPosition * ( -1 ); } というように、on アクションが使えるようになりました。ボタンやムービークリップで使う on と同じように、オブジェクトアクションとして設定できます。スライダが動いた時の関数を作って、それが定義されているパスが云々・・・と難しいことで悩まなくても済むようになりました。 この場合気をつけることは、スクロールバーから見たスクロール対象へのパス、移動の処理に変数を使う時はそのパスなどだけです。 スライダの大きさ・範囲を決める setScrollProperties の書式・考え方、およびパラメータの扱い方などは、今まで通りです。 ActionScript のバージョンについては調べきれませんでしたが、2.0 にしておいた方が無難かも知れません。 デザインも Windows XP 風のおしゃれなデザインになりましたので、入れ替えてみるのも悪くないと思いますよ。
補足
DPEさん、 そうです、先日教えて頂いたものを参考にしながら、他の質問でお教え頂いた内容も加えて作っています。 ・label ・script ・mask ・Image ・scrollBar ルート(シーン1)のレイヤーの構成はこのような感じです。 上記ルートのscriptレイヤーの1フレームにお教え頂いたscriptを記述しました。 function Sheet_Scrolling() { Image._x = sc_bar.getScrollPosition() * ( -1 ) + 100 ; } sc_bar.setScrollProperties( 50 , 0 , 100 ); sc_bar.setChangeHandler( "Sheet_Scrolling" ); これは意図した通り動いています。 と言う事は、ルートの配下にThumb_nailと言うムービーインスタンスを配置する。 そのThumb_nailインスタンスの内容は、 ScrollBarコンポーネントを配置したレイヤー、マスクレイヤー、マスクレイヤーの配下にsheetと言うムービーインスタンス、更にそのsheetの配下にtargetと言うダミーのムービーインスタンス、こういう事ですね?。 そして、scriptは全てThumb_nailの中のフレームアクションとして記述すると言う事ですね。 sheet内のscriptでJPEGファイルを全て読み込むという処理を記述した場合、sheetのタイムラインを利用してループ処理を行なうと思うのですが、Thumb_nail内のScriptとの関係はどのように考えれば良いのでしょうか?。 sheet内では、1フレームにファイルを読み込む処理を記述し、NG(Not Found)であればフラッグを立てる。 3フレーム位のところでscriptを記述し、フラッグを判定しOKであればtargetインスタンスの複製を作成し、そこにJPEGを読み込んで当該の座標に配置し、1フレームにジャンプする。 こんな構成で考えていますが、Thumb_nail内のscriptはどのフレームに記述したら良いのかが今一理解出来ていません。 やはり、このscriptもsheet内のscript同様に、タイムラインを使ってsheet内の処理が終わったかどうかを判定しながらScroolのscriptが動くようにコントロールしなければならないのでしょうか?。 そもそも、お教えいただいた上記scroll処理はどんなタイミングで呼び出される(動く)のでしょうか?。 どうぞ宜しくお願い致します。
お礼
いつもいつもありがとうございます。 他の質問で引き続きお聞きしておりますので、この質問に関しましては一先ずCloseさせて頂きます。