- ベストアンサー
onPressに関する質問
- フレームに配置したムービークリップに外部のJPEGを読み込んで表示するスクリプトで、マウスを移動させても形状が変わらないことに対する質問です。
- loadMovieでJPEGを読み込んだ後、ムービー上でマウスの形状が変化しない現象について質問しています。
- マウスの形状が変わらないことに対して、どのような原因が考えられるのか質問しています。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
ActionScript はオブジェクト指向の言語、と言われます。 オブジェクトの考え方は、様々なスキル(技能)を持った人を必要なだけ連れてきて、それぞれに仕事を任せるようなものです。 ステージにムービークリップのインスタンスを置き、インスタンス名を付けると、それだけで、MovieClip というスキルを持った人を1人、雇ったことになります。 ActionScript で new 演算子を使うことで雇うタイプの人もいます。MovieClipLoader や LoadVars はこのタイプです。 今、読み込みたい画像が5つあるとします。 画像の受け皿としてムービークリップが必要ですから、ムービークリップも5つ必要になります。となると、この時点で MovieClip を5人、雇ったことになります。 MovieClip は様々なスキルを持っていますが、そのうちの1つ、loadMovie を使って画像を読み込むとします。 MovieClip.loadMovie で1度に読み込める画像は1つだけ、しかも読み込む受け皿は自分自身に固定ですので、MovieClip に頼んで5つの画像を読み込むには、MovieClip は5人ともフル稼働ということになります。 ループを利用して for( i = 1 ; i <= 5 ; i++ ) { this[ "clip" + i ].loadMovie( "image" + i + "jpg" , i ); } このようにすると、スクリプトは1行なのですが、実際に稼動しているのは clip1 ~ 5 の5つのオブジェクトです。 では、MovieClipLoader はどうかと言いますと。 load_obj = new MovieClipLoader(); で、MovieClipLoader を1人、雇います。 MovieClipLoader は画像や swf ファイルの読み込みのプロです。MovieClip と違い、読み込みを1件ずつしか管理できず、それも読み込み先のムービークリップが固定などという不器用な仕事はしません。 例えば、5つの画像を5つのムービークリップに読み込むなら、 for( i = 1 ; i <= 5 ; i++ ) { load_obj.loadClip( "image" + i + "jpg" , this[ "clip" + i ] ); } この場合、稼動しているのは load_obj ただ1つだけです。 MovieClipLoader は取引台帳のようなものを持っていて、複数の読み込みを全て1人で管理する能力があると考えると、分かりやすいかも知れません。 この台帳には、受注した読み込みの進捗状況が事細かに書かれており、必要に応じて個別の情報を見せてもらうこともできます。 例えば、上記のように5件の読み込みの注文を出しておいて、 load_obj.getProgress( clip1 ); このようにすると、clip1 に読み込む総容量と読み込んだ容量を教えてくれます。(戻り値が2つあるため、戻り値を利用するには少々コツが必要です) また、それぞれの画像の読み込みが終わった時や、もしエラーが起きた時はこのようにしてほしいと、予め取り決めをしておくと、全ての読み込み作業で同じ処理をしてくれます。 なお、リスナーオブジェクトを先に登録し、イベントの情報をこちらに渡して処理させることもできます。いうなれば、MovieClipLoader の専属アシスタントを付けるようなものでしょうか。ヘルプに載っているサンプルは、リスナーオブジェクトを使った例です。 リスナーオブジェクトは普段は使い道がよく分かりませんが、例えば電子会議のように、1つのムービーに複数の閲覧者が接続していて、全ての閲覧者に同じ画像を配信したい場合などに真価を発揮します。 ------------------- 今さら何ですが。 そもそもエラーを利用してファイルの存在を確認するという発想は、フォルダに画像がいくつあるか Flash 側では把握できないものを、何とかして存在するだけ読み込みたいというところから出たはずです。 それが、ファイル名(もしくは管理番号などのヒント)を配列で与えて管理するのでしたら、いちいちエラーを利用してファイルの存在を確認したりせず、最初から、その配列の中身を元に読み込みの指示を出してはいかがでしょうか。 配列の要素がいくつあるかは、Array.length というプロパティで分かります。 例えば配列名が filename_tbl とすると、 for ( i = 0 ; i < filename_tbl.length ; i++ ) { //ムービークリップを複製し、画像を読み込む sheet.target.duplicateMovieClip( "b" + i , i ); sheet[ "b" + i ].loadMovie( filename_tbl[ i ] ); } 最初からファイルの数や名前が分かっていれば、for ループも利用できます。ただし、これはあくまでも読み込みの指示を出すだけですので、読み込みの完了を待って次の処理をするには、フレーム間のループも必要です。 配列のインデックスは0から始まります。ムービークリップを複製する時の番号も0から始めると、ループカウンタと管理番号がズレなくて便利です。 例えばファイルが5つなら、filename_tbl の長さである length プロパティは5ですが、インデックスの番号は0~4です。ループの終了条件を i <= filename_tbl.length と、5”以下”にしないよう、ご注意ください。 サムネイル画像でクリックを検出するには読み込みの完了を待たなければならないのは、#1で書いた通りです。 onClipEvent(data) を利用して読み込みが完了したファイルの数をカウントし、この数と filename_tbl.length を照合して全ての読み込みの完了を検出できます。 この場合はファイル名も読み込む数も先に分かっていますから、MovieClip.getBytesTotal と MovieClip.getBytesLoaded でもロード完了率を算出できると思います。 なお、読み込みが途中で失敗すると getBytesLoaded の値が狂うこともあり得ますので、getBytesTotal と getBytesLoaded の値を照合する方法はオススメしません。 ------------------- 参照しようとした変数が undefined になる理由は、大抵は階層の間違いですが。 var_product や var_menu がメインのタイムラインにあるのでしたら、サムネイル内のボタンやムービークリップから参照するには、_root までのターゲットパスが必要です。 ボタンシンボルにはタイムラインがないので、ボタンシンボルは変数や関数を保持できません。ボタンインスタンスに相対パスで変数や関数を利用するスクリプトを書くと、親の階層にある変数や関数と見なされます。ですから、ボタンインスタンスへのスクリプトでは、親の階層までのターゲットパスが省略可能です。 ムービークリップをボタンとして使う場合は通常通り、自分の階層までのターゲットパスが省略可能です。 別の疑問は、できるだけスレを分けてください。 追加の便乗質問は1つくらいなら構わないのですが、あれもこれもとなると、スレが長くなったり、質問と回答の内容がズレていったりして、ページも重くなりますし、後から見る人の迷惑になります。
その他の回答 (2)
- DPE
- ベストアンサー率85% (666/776)
拡大画像もクリックできるようにしたい、ということでしょうか? 拡大画像を表示する部分は1つでしょうか?1つでしたら、読み込み先のムービークリップとして、ステージなり何かのムービークリップ内なりに配置しているムービークリップ(ご質問文にあるスクリプトでいうところの、image_mc に相当するもの)があるかと思います。これに on(press) を指定するのが、一番簡単です。 onPress = function () ・・・では、拡大画像の表示部分に画像を読み込み直す度に無効になってしまいます。on(press) を設定したムービークリップインスタンスでは、何度も loadMovie で画像を読み直しても、クリックの検出はずっと行われます。 (ただし、画像を読み込んでいる間は一時的に検出されなくなります) 拡大画像の表示部分が1つではなく複数の場合は、サムネイル表示部分と同じ要領で、全ての読み込みの完了を待ってから onPress を定義してはいかがでしょうか。 ---------------- ***.onLoadError = function ( target_mc:MovieClip , errorCode:String ) ・・・ ↑target_mc や errorCode は仮引数といって、関数を定義する時だけ使われる仮の引数です。 実在する変数を引数にして関数を定義すると、その変数専用の関数になって汎用性がなくなってしまいます。 そこで、仮の引数を使って関数を定義するわけです。関数を呼び出すと、定義の時に仮引数で書いた部分が引数で渡されてきた実在の変数や値と置き換わり、処理が行われます。 先のエラーイベントの関数で言いますと、エラーが起きて実際に関数が呼び出される時は、第1引数にエラーが発生したムービークリップへの参照、第2引数にエラーの種類を表す文字列が渡されます。関数の中で target_mc や errorCode と書いた部分が、これらと入れ換わると思ってください。 関数の中でこれらの情報をどのように使うかは自由です。不要なら利用しなくても構いませんし、文法上も問題はありません。 MovieClip の loadMovie は、1つのムービークリップにつき1件の読み込みしか管理できません。 1件しか管理できないということは、画像が読み込まれる対象も読み込みの進捗情報を持っているのも、必然的に自分自身ということになりますから、”どのムービークリップか?”という指定は不要です。(オブジェクト名がそのまま、画像が読み込まれるムービークリップの指定になります) MovieClipLoader は、1つのオブジェクトで何件もの読み込みを管理できます。 そのため、どのムービークリップでイベントが起きたのかを判別できる設計になっています。 例えば、読み込む画像がいくつかあって、読み込み終了後にとりあえず非表示にしておきたい場合は、 onClipEvent(data) { this._visible = false; } MovieClip.loadMovie では、このスクリプトを全部のムービークリップインスタンスに書かなければなりません。 MovieClipLoader の onLoadInit イベントハンドラを利用すると、 load_obj.onLoadInit = function ( target_mc:MovieClip ) { target_mc._visible = false; }; この定義を1回だけしておくだけで、画像がいくつあっても、load_obj という MovieClipLoader オブジェクトの loadClip メソッドで読み込む限り、いずれも読み込み完了と同時に非表示になります。 ちなみに、今まで何となく使ってきた LoadVars.onLoad イベントハンドラの引数 success も、実は仮引数です。onLoad イベントが発生した時、つまり読み込みが終わった時、読み込みが成功した場合は true( 1 )、失敗した場合は false( 0 )を引数として、関数が呼び出されていただけのことです。 仮引数の名前は自由に決められます。target_mc ではなく target_clip 、success の代わりに load_status などにしても、同じように動作します。 > 素人にとっては、なんと使い勝手の悪いHELPなんだと思います。これじゃ、HELPの為のHELPが必要です。 まあ、Flash に限らずどのソフトでも、ヘルプは分かりにくいです。 特に ActionScript のサンプルは、ただでさえもメソッドなどが長い名前になっているのに、変数やオブジェクトに my******などと長~い名前を付けているので、プログラムが分かりにくくなっています。 おまけに、ActionScript 2.0 から取り入れられた、” : ”で区切って変数などの型を明示する書き方で書かれており、これがまたゴチャゴチャして余計に見にくいです。 今までご紹介したサンプルは、スクリプトがゴチャゴチャすると分かりにくいかと思い、型の明示は省略させていただきました。あってもなくても動作自体にはあまり関係ありませんが、気になるようでしたら適宜追加してください。
お礼
すみません、教えて下さい。 ムービークリップのアクションとして、 on(Press) { getURL("http://www.xxxx.com/prd.aspx?sid="+var_product) ; } こんなScriptを記述しました。 1フレームには、 var var_product = "" ; switch(var_menu) { case "aaa": var_product = "11101" ; break ; case "bbb": var_product = "11102" ; break ; case "ccc": var_product = "11302" ; break ; default: break ; } このようなScriptを記述しました。 1フレームでは正しくvar_productの内容が入っていますが、ムービークリップのアクション内でTraceで確認すると var_productがundefinedになってしまいます。 var_product以外の変数も全てundefinedになります。 フレーム構成は、 1フレーム:変数の定義、関数、上記のmenuの判定。 ScrollBar,Mask,サムネイル 5フレーム:上記ムービークリップを配置。 6~7フレーム:JPEGの読み込み、設定 ムービークリップは、当初1フレームに配置していましたが、タイミングの問題があるのではと思って5フレームにズラしてみました。
補足
拡大画像クリックの件、ありがとうございます。確かにそうですね、読み込む先は今回は一箇所だけ(image_mc)ですのでムービークリップアクションで良いわけですよね。 「MovieClipLoader は、1つのオブジェクトで何件もの読み込みを管理できます。」 この意味をもう少しお聞かせください。(理解出来ていません。) 今回はサムネイル表示するJPEGのファイル名をカンマで区切ったテキストを作成し初期処理で配列に取り込み、それを基にしてJPEGの読込み処理を行なっています。 2フレームにloadClipを定義し、「complete」の処理でduplicateMovieClip以降の処理と、次のJPEGの読込みのためにインデックスのカウントアップを行なって1フレームにジャンプさせています。(ここで読込みのループをさせています。) onLoadErrorの定義で最終的な処理を行なうフレームにジャンプさせて終了しています。 ここで、私もcompleteの処理の前に、例えばonLoadStartかonLoadInitの定義で次の読込みを実施する、即ちloadClip()を関数内で定義しておき、2件目以降はonLoadStart内でonLoadClip()が定義されている関数を呼び出すようにすればと思っていましたが、読み込む際に配列から情報を取り出す為とduplicateMovieClipで複写したムービークリップにインスタンス名を付ける為にカウントアップしているインデックスの値が狂ってしまわないかと心配になり躊躇しているところです。 その代わりと言っては何ですが、ロードした画像をそのままにしておくよりもunLoadした方が動作がスムーズになると聞いて、サムネイルを含めロードしたJPEGなどはすぐにunLoadする記述を入れました。 これって正しいのでしょうか?。unLoadもLoadと同様にI/Oが発生すると言う事で、処理的には負荷がかかる事にはならないのでしょうか?。
- DPE
- ベストアンサー率85% (666/776)
スクリプトに誤りはないのですが、定義するタイミングが良くないようです。 ローカルでテストしてみても、loadMovie の直後に onPress を定義すると無効になってしまいます。 しかし、loadMovie から2、3つほど後のフレームで定義すると、この定義は有効になります。 インスタンスに on(press) で定義した時は、画像の読み込み終了後から press イベントが検出されるようになります。 http://okweb.jp/kotaeru.php3?q=992878 では、loadMovie の終了を待たずに onPress を定義しても上手くいっていましたので、どのくらいのタイミングから定義が有効になるか(厳密には読み込みが終わらなくてもいいのかどうか)、もしくは、本当は上手くいかないのにたまたま上手くいっていただけなのかどうかは分かりませんが・・・ 仮に、読み込みが終わる前に onPress を定義して、これが有効になるとしても、画像を読み込み中で何も表示されていないムービークリップがクリック可能(カーソルを移動すると形が変わる)というのは、少々不自然ではないでしょうか。 見ている人への配慮から考えても、onPress は読み込みの終了を待って定義した方がよさそうです。定義するまでは未定義のままですから、当然ながら、クリックしても何も起きませんし、カーソルの形も変わりません。 loadMovie には2種類あります。 画像や swf ファイルと置き換えるインスタンス名や階層( _level )を指定する loadMovie アクション( Flash Player 3 から使用可能)と、MovieClip オブジェクトのメソッドの1つである loadMovie( Flash Player 5 以降で使用可能)です。 loadMovie アクションは本当に読み込むだけの機能しかなく、読み込みの終了を検出する方法がありません。 MovieClip.loadMovie では読み込み終了時に data というイベントが発生し、読み込みの終了を検出できます。 ただし、loadMovie メソッドを呼び出したムービークリップインスタンスでは ***.onData = function ()・・・の書き方は正常に機能しませんので、onClipEvent(data) を利用する必要があります。
お礼
すみません。#2の「お礼」の内容について、私のミスに気が付きました。 「_parent」が抜けていました。 ただ、on(Press)にすると一度クリックしただけなのにgetURLの処理が2度とか3度実行される事があります。 on(release)にすると正しく1度だけの実行になります。 全く違う内容で恐縮ですが、ご存知でしたらお教えください。 #2の「補足」い対する回答も宜しく御願い致します。
補足
いつもお世話になります。 私も試してみましたが、ご指摘の通り少し後のフレームで定義すると正しく動きました。何故ですかねぇ?。 でも、今回は下記のようにサムネイルを表示した分だけ、クリック時の処理を関数で処理しています。 image_set()と言う関数の中で選択されたサムネイルの拡大画像を表示し、そのムービーに対してonPressを定義したいのです。 for( i = 1 ; i <= (var_setctr) ; i++ ) { sheet[ i ][ "var_image_no" ] = i; sheet[ i ].onPress = function () { var_suffix = this.var_image_no; image_set() ; } ; } なかなかうまく動きません。 movieClipLoaderを試しに使ってみましたが、結構早くなった気がします。読込みが完了したかどうかを確認する前にロード出来ていたりするので、今までとは勝手が違うので戸惑っています。HELP文中の = function(target_mc:MovieClip, errorCode:String) の「target_mc」って何の事だか分かりませんが、そのまま使っていてもエラーにはならないし、正常に動いているようだし。 素人にとっては、なんと使い勝手の悪いHELPなんだと思います。これじゃ、HELPの為のHELPが必要です。
お礼
まず、便乗質問の件は申し訳ありません。 話のつながりで、別の質問を設定するとお答え頂く方(DPEさん)が戸惑われないかなぁと思い、長々と質問する羽目になりました。 エラーハンドリングの件、おっしゃる通り最初はファイル数が分からない、ファイル名をSequencialに付け直すという発想からでしたが、あまりのファイルの多さにファイル名の付け替えに要するワークロードなどを考えた時、コントロールするテキストファイルを用意した方が得策だと思い、途中で方針変更となりました。 ご指摘のように配列に格納されている数だけループで処理すればロジックも見易くなり簡単になりますね。 それに、MovieClipLoader を使えば読み込みの完了はonLoadComplete()内のロジックで実装すればフレームのループも必要無くなりますよね。 ありがとうございます。モヤモヤはがすっきり晴れました。