- ベストアンサー
外部変数で条件分岐
ムービークリップ内にダイナミックテキストを配置、インスタンス名をkijibox01、参照する変数名をkiji01としています。 ダイナミックテキストはトゥイーンさせているので、後々は記事トピックをボタン切り替えでひとつひとつ表示させ、さらにリンクがある記事にはボタン処理を施してジャンプさせるような仕組みを考えています。 ムービークリップ上のスクリプトは、 onClipEvent (load) { //log.txtから記事トピックを取得、url.txtからジャンプ先のURLを取得 this.LoadVariables("log.txt"); this.LoadVariables("url.txt"); //mcを押した際、url.txt内のURLにジャンプ this.onRelease = function() { this.getURL(url01); }; //ロールオーバー・アウト時のテキストカラーの変更 this.onRollOver = function() { this.kijibox01.textColor = 0x6633cc; }; this.onRollOut = function() { this.kijibox01.textColor = 0x000000; }; } で問題なく動くのですが、記事トピックにリンクが必要無い場合はボタン処理などを入れたくないので、リンクが無い時はurl01の変数をnoURLとし、条件分岐でurl01がnoURLでは無い場合のみボタン処理を与えるようにしたいのですがうまくいかずに困っています。 onClipEvent (load) { this.LoadVariables("log.txt"); this.LoadVariables("url.txt"); if (url01 != noURL) { this.onRelease = function() { this.getURL(url01); }; this.onRollOver = function() { this.kijibox01.textColor = 0x6633cc; }; this.onRollOut = function() { this.kijibox01.textColor = 0x000000; }; } } と記述したのですがうまくいきませんでした。 正常に動くスクリプトをifで区切っただけに思えるのですが何か間違っているのでしょうか? わかりにくい説明で恐縮ですがアドバイスをお願いします。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
読み込みが完了する前に変数を if 文で判断しようとしているので、変数 url01 が未定義( undefined )になっていて失敗しているのだと思います。 外部から読み込んだ変数を使って何かをする場合は、必ず、読み込みが正常に完了したことを確認してから次の処理をするようにしましょう。 例えば、log.txt の中身が test=log だとします。日本語(全角文字)ですらない、単純なデータです。 これを this.loadVariables( "log.txt" ); trace( test ); として trace アクションで表示させると、undefined と表示されます。 しかし、2、3フレーム先で同じく trace アクションを実行してみますと、変数の内容が表示され、正常に読み込まれているのが確認できます。 つまり、読み込むテキストがどんなに短いものだったとしても、また、通信回線を介さないオフラインで再生する場合でも、読み込みの命令を出した次の瞬間に変数が読み込まれていることはありえないのです。 ところで、外部変数で条件分岐しない時は正常に動いたとありますが。 this.getURL( url01 ); このアクションは、ムービークリップがクリックされた時に実行されます。 テキストファイルは容量が軽く、単純なデータですから、数フレームのうちには読み込みは終わります。 クリックする頃には変数 url01 は読み込まれているので、あえて読み込みの完了を待たなくても問題なく動くのですが、安全なスクリプトかどうかは疑問です。 それから、外部から読み込んだ変数は、基本的には文字列として扱われます。 例えば url01=noURL という内容のテキストファイルを読み込むと、url01 に” noURL ”という文字列が入ります。 if 文で、変数に noURL という文字列が入っているかどうかの条件を書く時は if( url01 != "noURL" ) このように、" " でくくって書きます。 if( url01 != noURL ) では、noURL という変数に入っている値と比較していることになります。 読み込みの完了を待つ方法はいろいろあります。 MovieClip オブジェクト( MX 2004 ではクラス)の loadVariables メソッドで読み込むと、最後の変数が読み込まれた時に1度だけ、data というイベントが発生します。 これを利用してみてはいかがでしょう。 (↓各行頭に全角のスペースが入っています。コピーする際はご注意ください) onClipEvent(load) { //表示するテキストとURLの読み込み this.LoadVariables( "log.txt" ); this.LoadVariables( "url.txt" ); } onClipEvent(data) { //リンクがある場合はムービークリップをボタン化 if ( url01 != "noURL" ) { this.onRelease = function() { this.getURL( url01 ); }; this.onRollOver = function() { this.kijibox01.textColor = 0x6633cc; }; this.onRollOut = function() { this.kijibox01.textColor = 0x000000; }; } } ---------------------------------------------------------- 制御したいムービークリップやテキストの数が多い時は、多くの対象をできるだけ効率よくさばけるようにスクリプトやムービークリップを設計するといいですよ。 上記のような設計ですと、ムービークリップごとにスクリプトを書かなければなりません。 単に動けばいいだけというのならそれでもいいですが、例えばテキストの色を変えたくなった時には、複数のムービークリップに設定された全てのスクリプトを書き換えることになります。 これは大変な手間になりますし、書き換えるのを忘れたり、余計なところをいじって不具合の原因になったりすることも考えられます。 今回の場合は、 ・ロールオーバー/アウト時にテキストの色を変える ・クリックされた時、リンク先があればページを表示 こうした処理は、どのムービークリップでも共通するものです。 共通するものがあるなら、ムービークリップシンボルとして作った方が扱いやすくなります。 シンボルが1つあれば、インスタンスとして同じ機能を持った分身をいくつでも作れますし、仕様が変更になった時でも、このシンボルを修正するだけで済みます。 例えば、ダイナミックテキストのテキストフィールド” kiji ”を配置したムービークリップシンボルがあるとします。 このシンボルのフレーム1に、次のようなスクリプトを書きます。 //リンク先を保持 hp = ""; //テキストフィールドを文字列に合わせて伸縮 //テキストは左揃え kiji.autoSize = "left"; //ロールオーバー/アウトで、テキストの色を変える this.onRollOver = function() { kiji.textColor = 0x6633cc; }; this.onRollOut = function() { kiji.textColor = 0x000000; }; //クリックされた時、リンク先を表示 this.onRelease = function() { getURL( hp , "_blank" ); }; kiji.autoSize は、表示するテキストの字数に合わせてテキストフィールドの幅を変更する設定です。”left”にすると、単一行の時は、左端は固定で右方向にテキストフィールドが伸縮されます。 ムービークリップ自身に onRollOver や onRelease が定義されているので、予め配置されたテキストフィールドが大きすぎると、字のないところにカーソルが乗った時もてのひらのカーソルに変わってしまい、これでは少々不自然ですよね。 autoSize を設定しておくと、文字のあるところだけに反応するようになります。 これで、このシンボルのインスタンスは全て、字数に応じて伸縮する kiji というテキストフィールドとボタンとしての機能を持つことになります。 テキストフィールドには、表示する内容を管理している text というプロパティがあります。これを書き換えることで、テキストフィールドの表示を直接更新できます。 テキストフィールドの「変数:」の項目に変数名をしておくと、変数の内容を簡単に表示できて便利なのですが、変数が多い時はその分だけテキストフィールドを作らなければならなくなります。 text プロパティを書き換える方法であれば、変数名の指定は必要ありません。1つのテキストフィールドで、いろいろな変数を表示できます。 さて、このシンボルは表示する URL があろうとなかろうと、必ずマウスに反応するようになっています。 リンク先がない場合は反応しないようにするには、いろいろな方法が考えられますが、簡単なところで、enabled プロパティを false にしてボタンとしての機能を OFF にする方法をご紹介します。 enabled プロパティを false にしたボタンやムービークリップでは、rollOver や release イベントなどのボタンイベントが発生しなくなります。 (ムービークリップ特有の enterFrame 等のイベントは引き続き検出されます) 仮に、上記のシンボルのインスタンスを5つ配置したムービークリップ” main ”があるとします。 5つのインスタンスにはそれぞれ、clip1 ~ clip5 という名前を付けておきます。 log.txt と url.txt から読み込む変数も、固有の名前+通し番号で名前を付けます。仮に、topic1 ~ 5 と url1 ~ 5 とします。 外部から変数を読み込み、リンク先がない( noURL の時)時はリンクボタンにしないスクリプトは、大体、次のようになります。 このスクリプトは” main ”のインスタンスに設定します。 onClipEvent(load) { //表示テキストとURLの読み込み this.loadVariables( "log.txt" ); this.loadVariables( "url.txt" ); } //読み込み完了時の処理 onClipEvent(data) { var i; for( i = 1 ; i <= 5 ; i++ ) { //テキストを各テキストフィールドに表示 this[ "clip" + i ][ "kiji" ].text = this[ "topic" + i ]; //URLをムービークリップ内の変数に保存 this[ "clip" + i ].hp = this[ "url" + i ]; //表示するリンクがない場合、ボタンとしての機能を無効にする if( this[ "url" + i ] == "noURL" ) { this[ "clip" + i ].enabled = false; } } } Flash では、文字列を使ってインスタンスや変数を操作できます。 文字列でインスタンスや変数を操作するには eval 関数か配列演算子 [ ] を使います。eval 関数は Flash Player 6 からは条件が付きますので、ここでは配列演算子を利用しています。 clip1 ~ 5 は、それぞれ hp という変数を持っています。 for ループの中で this.onRelease = function() { getURL( this[ "url" + i ] ); } というように定義すると、ループの外では url +番号の変数が undefined になり、ページの移動ができません。 そこで、読み込んだ変数をムービークリップが持っている別の変数( hp )にコピーして、いつでも利用できるようにしています。 この例では、main のフレーム1に clip1 ~ 5 が存在していることが条件になります。 切り替えて表示するには、_visible プロパティを使って今表示するムービークリップだけを表示し、残りのものは非表示にするといった処理も必要です。 他にも、スクリプトで位置と表示する内容だけを変更するといった方法もあります。 この方法では、インスタンスも1つだけで済みますね。 スクリプトをなるべくあちこちに分散させない設計として、ご参考までに。
その他の回答 (1)
書かれている, ------------------------------------------------ if (this.url01 != noURL) { this.onRelease = function() { this.getURL(url01); }; this.onRollOver = function() { this.kijibox01.textColor = 0x6633cc; }; this.onRollOut = function() { this.kijibox01.textColor = 0x000000; }; } ---------------------------------------------- の部分ですが, url01など変数自体が元から全く存在しない場合は, -------------------------------------------------- if (this.url01 != null) { this.getURL(url01); } }; this.onRollOver = function() { if (this.url01 != null) { this.kijibox01.textColor = 0x6633cc; } }; this.onRollOut = function() { if (this.url01 != null) { this.kijibox01.textColor = 0x000000; } -------------------------------------------------- で動くと思います。 url01の値だけがない (url01=&url02=… みたいな) 場合は -------------------------------------------------- if (this.url01 != "") { this.getURL(url01); } }; this.onRollOver = function() { if (this.url01 != "") { this.kijibox01.textColor = 0x6633cc; } }; this.onRollOut = function() { if (this.url01 != "") { this.kijibox01.textColor = 0x000000; } -------------------------------------------------- で動くと思います。 でも,カーソルは指マークに変わってしまいますけどね。 そこのところはご容赦。
お礼
nullの存在を忘れていました。 また、外部変数は文字列として扱われることも見落としていました。反省しきりです。。 アドバイスしていただいた方法を早速試してみたのですが、残念ながら同様の症状に陥ってしまいました。 原因は#2の方のアドバイスにある、変数の読み込みが終わってないうちに条件分岐を行おうとしていたのが原因のようです。 ""を用いて変数が空欄なのか判定することができたりと、アドバイスは参考になりました。 ご回答ありがとうございました。
お礼
アドバイス頂いた通り、条件分岐のスクリプトを onClipEvent(Data)で括ることで正常に動作しました。 変数が正常に読み込まれているかをプレビューでの 変数一覧表示によって行っていたので今回の症状に 気づくことができませんでした。反省… その後のスクリプトは本当に効率が良く、 合理的なのでとても参考になりました。 このように記述するには慣れだけでなく想像力も必要としそうですね。精進したいと思います。 初心者にもわかりやすいアドバイスで感謝しています。 ご回答ありがとうございました。