5/31日のF-siteセミナー用に作成したレジュメです。セミナー中には言えなかった情報や、見せられなかったflaファイルなどもあります。僕はこれを見ながらしゃべっていただけですので、うまくすればあなたにもセミナーができてしまうかもしれません(笑)

当日のことを思い出しながら、活用していただければ幸いです。


1.
こんにちは。F-siteの宮地成太郎です。普段は実験的なFLASHを制作して自分のページ(http://www.colorful4u.com/)で発表したり、小さなプロジェクトちょこちょこやってます。2代目のF-siteのカバーアートを作ってます。
今回は「FLASHインターフェース大分析」、ということでFLASHで制作されたインターフェースのテクニックをみなさんに伝授します。ただ何から何まで、というわけには時間の都合上いきませんので、僕と桜井さんで合計2つのサイトをピックアップして面白いところだけを解説することになります。僕は森アーツセンターのWEBサイトを参考に、解像度に依存しない次世代レイアウトのスタンダードになるであろう技術に焦点を当て、解説していきたいと思います。
スクリプティングのレベルは若干中級者向けになっています。ムービーの階層構造、つまり_rootだのインスタンス名だのがわかってれば多分理解できます。

では解説するサイトの方から紹介していきたいと思います。解説するのはいま話題になってる六本木ヒルズの中の森アーツセンターのWEBサイトです。

【起動】http://www.moriartscenter.org/

(オープニングムービーを見ながら)
森アーツセンターは今年4月にオープンした六本木ヒルズ森タワーの最上部に位置する複合文化施設で、
屋上の東京スカイデッキ(空中回廊)、森美術館(52階〜54階)、東京シティビュー(展望ギャラリー)(52階)、六本木ヒルズクラブ/ミュージアムカフェ(飲食施設)(51階)、森アーツセンターオフィス/ミュージアムショップ(50階)、六本木アカデミーヒルズ(会員制ライブラリー)(49階)などで構成されています。六本木ヒルズの中核となっている施設です。
制作はビジネスアーキテクツ。アートディレクターにMONO*craftsの中村勇吾氏が参加しています。
ビジネス・アーキテクツはこのサイトの他にも森ビル関係で六本木ヒルズの本サイト、あと先ほど紹介した森アーツセンター内の東京シティービューのサイトの方も制作してます。後者のサイトは東京の景観が見わたせるパノラマFLASHなんかもあるんですが、こっちも結構面白いので見てみるといいかもしれません。「東京シティービュー」で検索すればすぐに出てくると思います。


2.
ではこのサイトのどこを解説するのかといいますと、「ウィンドウをリサイズしたときのレイアウト自動調整スクリプト」です。
口頭で説明しても訳がわからないと思いますので、実際にどういったインターフェースなのかを見ていきましょう。

【ブラウザをリサイズしながら】
ウィンドウをリサイズすると…すごいことが起こります。ステージのサイズを取得できるというFLASH MXの新機能をうまく使っていると思います。こういう形のFLASHですと、PowerBookやバイオWなどのワイド液晶を搭載するマシンでもきれいにレイアウトすることが出来ますよね。非常に実用性のあるインターフェースです。
FLASH5までだとブラウザにswfファイルのサイズを合わせるにはfscommandのallowscaleをtrueにしたり、パブリッシュ設定をいじるしか方法はありませんでした。今回のスクリプトは新たなレイアウトのスタンダードになっていくのではないかと、個人的にはかなり期待していたりします。
3
では解説していきたいと思います。どうやっているのか。方法はステージ配置された普通のムービークリップをステージのサイズに合わせて移動しています。処理の流れを言いますと「ステージがリサイズされるたびにステージサイズを取得し、それに合わせてムービークリップを移動させる」という方法をとなっています。
大体おおざっぱに言うとこういう流れになっています。
4
では具体的な解説に入っていきます。
ユーザーによってステージのリサイズが行われたら、処理を実行するというスクリプトを解説していきます。
やっとここからセミナーらしくなってくるので、よく聞いておいてください。ステージのリサイズを通知するには、「リスナー」というものをを使います。リスナーは、MXからあらたに取り入れられた考え方で、イベントを受け取るためのobjectオブジェクトです。F-siteのセミナーを毎回しっかり受けていられる方は覚えているかと思いますが、昨年の9月7日に野中さんがこのイベントリスナーについて解説されていましたね。
今回はリスナーについて理解するという趣旨のセミナーではないので、わからない方は聞き流してかまわないと思います。ただ、書き方はちゃんとメモしておきましょう。

じゃあスクリプトを記述します。ムービーの1フレーム目に

【記述 myListener=new Object()】

myListenerというobjectオブジェクトを明示的に生成します。
いろんなオブジェクトでこの書き方はよく使いますね。

【記述 myListener.onResize=function(){】

ここでステージがリサイズされたときのアクションを決定します。このfunctionの中に実行したい処理を書きますが、順を追って説明していきますので、とりあえずここはまだ埋めません。

【記述 Stage.addListener(myListener)】

ステージオブジェクトにaddListener でリスナーを追加します。 Stage.removeListener(myListener)なんていうのを使えばリスナーを削除することも出来ます。あたりまえですが削除するとステージのリサイズは通知されなくなります。
まとめますと、スクリプトは次のようになったかと思います。

myListener = new Object();
myListener.onResize = function() {
   //ここは空にしておきます
};
Stage.addListener(myListener);

では実際にステージのリサイズを通知してみましょう。
先ほどからにしておいたfunctionの中にtrace("OK")と書きます。
これでムービープレビューをすれば、ステージがリサイズされるたびに出力ウィンドウにOKが表示されるはずですよね。今更ですがtraceは変数の中身を出力ウィンドウに表示するスクリプトです。
まとめると、スクリプトは次のようになります。

myListener = new Object();
myListener.onResize = function() {
   trace("OK")
};
Stage.addListener(myListener);

【ムービープレビューをし、ステージをリサイズ】

OKが出力ウィンドウにでてきましたね。ステージのリサイズされたらfunctionの中が実行されるようになってますね。これで第一段階が終了です。

5
では次の手順に入ります。「リサイズ後のステージサイズを取得」を解説していきたいと思います。
聞くと難しそうですが、ステージのリサイズを受け取るスクリプトはすでに完成していますから、あとは簡単です。先ほどtraceを書いたfunctionの中にステージサイズを取得するスクリプトを書けばいいだけです。そうすればステージがリサイズされるたびにステージの大きさが求められることになります。ステージのサイズを求めるには、Stageオブジェクトを使います。

【記述 stageW=Stage.width】
【記述 stageH=Stage.height】

まとめると、スクリプトは次のようになります。
myListener = new Object();
myListener.onResize = function() {
   stageW = Stage.width
   stageH = Stage.height
};
Stage.addListener(myListener);

そしてハマりがちなのが、拡大・縮小の設定です。最初に言ったとおりに、swfファイルの拡大・縮小でメニュー位置を移動させているわけではないので、パブリッシュ設定→HTML→伸縮は「拡大・縮小なし」としておきます。
なお、[伸縮]の[拡大/縮小なし]は、以下のスクリプトで代替すること ができます。
Stage.scaleMode = "noScale";
これをムービーの1フレーム目のフレームアクションに書いておけばHTML側で設定しなくてもOKです。

これは簡単ですね。stageW、stageHという変数にそれぞれステージの横と縦の大きさを代入します。
ではせっかくだからstageWとstageHの値をtraceしてみるか…。とか思ってムービープレビューしてみると値が若干違ってtraceされてしまいます。ムービープレビューのウィンドウの大きさを返してくるのでバグではないと思うのですが、まぎらわしいのでテキストフィールドを作り、変数名をそれぞれstageW、stageHとしてパブリッシュプレビューで確認します。

【ステージに変数名stageW、stageHのダイナミックテキストフィールドを作成し、パブリッシュプレビュー】

これでしっかりステージがリサイズされるたびにステージのサイズを取得できました。

6
次へいきます。「今取得したステージサイズをもとに、ムービークリップの位置を変更」を解説していきます。
これもスクリプトの中級者であれば解説するまでもないと思いますが、初心者の方も多数いらっしゃいますので解説していきます。中級者の方はスクリプトを予想しながら聞いてみてください。ステージにbarXという名前を付けたムービークリップと、barYという名前を付けたムービークリップを配置しておき、先ほどのリスナーfunctionの部分にbarX、barYの_x、_yを変更するスクリプトを記述します。


【1フレーム目を確認 先ほど書いたスクリプトがすでに書かれている】

【barX._x=stageW】
ムービークリップ「barX」のx座標にステージの幅(変数stageW)を代入しています。
【barY._y=stageH】
ムービークリップ「barY」のx座標にステージの高さ(変数stageY)を代入しています。
まとめると、スクリプトは次のようになります。

myListener = new Object();
myListener.onResize = function() {
   barX._x = Stage.width
   barY._y = Stage.height
};
Stage.addListener(myListener);

ちなみにこのレイアウト用のムービークリップは中心点をステージの縦、横に合わせてください。
【レイアウト用のムービークリップの解説】

【パブリッシュプレビュー】
ちょっと汚いですね。大きな解像度のディスプレイのためにレイアウト用のムービークリップは大きめに作っておきます。それと移動する位置がステージサイズに合っていません。
これはswfファイルの実際のステージサイズより大きなサイズでswfファイルを表示したときの表示位置が中央になっているためです。言葉で言うとわかりにくいので、実際に見ていきましょう。

【起動 data.files/flash/align.fla】
alignは、パラメータは位置によってこのように決まっています。
Stageサイズを取得して、使いますので基本となる位置は左上にある方が理想ですよね。FLASHでは座標関係は原点が左上にありますからalignのパラメータを"TL"とします。

【起動 data.files/flash/chuou.fla】
ステージの背景を濃い灰色にして、ステージサイズいっぱいに薄い灰色を塗ったFLASHです。これを使ってFLASHの表示位置について見ていきたいと思います。
【Stage.alignを"TL"に設定する前とあとで見比べてみる】

【data.files/flash/align.flaを閉じる】

【記述 Stage.align="TL"】
まとめると、スクリプトは次のようになります。

Stage.align = "TL"
myListener = new Object();
myListener.onResize = function() {
   barX._x = Stage.width
   barY._y = Stage.height
};
Stage.addListener(myListener);

7
ついに最後の仕上げです。moriartscenterのサイトはなめらかにムービークリップが移動してましたよね。でも今僕が書いてるスクリプトは動作が一瞬で終わってしまいます。
今回のタイトルはFLASHインターフェース大分析ですので、限りなく近いモノを作りたいと思います。そのためには次のスクリプトが必要になります。

【記述 barXに】
onClipEvent(enterFrame){
   _x += (posX-_x)/5
}
【記述 同様にbarYにも】

【マウスで式を指しながら】
この式を人間語に翻訳しますと「現在のムービークリップの位置に(目標の位置-現在の位置)/5を
【onClipEvent(enterFrame)を指しながら】
毎フレーム足し続けます。毎フレーム実行するというハンドラに囲まれているわけですからね。
ここでちょっと注釈というか、最初のリスナーがわからなかった人はここにStage.widthを直接入れてもかまわないと思います。そこまで重い処理ではないので体感速度に変化はほとんどありません。ただ、せっかくFLASH MXで作るのですから、解説はリスナーを使ったやり方で進めていきたいと思います。
ここではposXを目標の位置とします。
一回計算するごとに足される値、つまり移動する距離は減っていくので、ムービークリップはだんだん減速していくという動きになるのです。この式ができればほぼ完成も同然です。最後に先ほどのリスナーのスクリプトのfunction内にステージサイズをムービークリップのposXに代入するスクリプトを書けば完成です。

8
ステージサイズをムービークリップbarXの中のposX、barYの中のposYに代入するスクリプトを記述します。
これで完成しました。実際の動きを見てみましょう。

まとめると、スクリプトは次のようになります。

Stage.align = "TL"
myListener = new Object();
myListener.onResize = function() {
   barX.posX = Stage.width
   barY.posY = Stage.height
};
Stage.addListener(myListener);

(barX、barYのクリップアクションに)
onClipEvent(enterFrame){
   _x+=(posX-_x)/5
}

【パブリッシュプレビュー&何度かリサイズ】

これで完成です。
今回解説したStageの幅、高さの求め方のスクリプト、それと減速しながら目標に向かうスクリプトなんかはホントに重宝しますので、みなさんぜひFLASHのインターフェース制作に役立てていただければいいかな、と思います。
それと最後に実例紹介と言うことで、今回使ったStageオブジェクトを駆使したサイトをご紹介します。
最近nttdataがリニューアルされまして、そこでStageオブジェクトを使ったテクニックがふんだんにつかわれています。
リサイズするとこのムービークリップがサイズに合わせて移動するんです。すっごく面白いので、ぜひ見てみてください。

NTTデータ
http://www.nttdata.co.jp/

あと減速しながら目標に向かうスクリプトなんていうのは最初に紹介したF-siteのカバーでも使われてるテクニックです。この場合はグラデーションのムービークリップにさっきの式を書いてます。

F-site カバーアート(2代目)
http://www.f-site.org/

補足(セミナーではしゃべっていない内容です)
セミナー後に野中さんからご指摘を頂き、「ブラウザを一度リサイズしないとムービークリップがステージのはじに移動しない」という問題を解決することが出来ました。方法は、以下の通りです。

メインのタイムラインの1フレーム目、myListenerを設定している所の最後の行に
myListener.onResize();
を追加します。

まとめると、メインのタイムライン1フレーム目に記述されるスクリプトは次のようになります。
Stage.align = "TL";
myListener = new Object();
myListener.onResize = function() {
   barX.posX = Stage.width;
   barY.posY = Stage.height;
};
Stage.addListener(myListener);
myListener.onResize()

さらに、野中さんよりムービークリップの1フレーム目(今回の例で言うとbarX、barYの中)に書くだけで今回解説したスクリプトと同じような動きを実現するスクリプトを頂きました。う…美しい…

this.nSpeed = 0.2;
Stage.scaleMode = "noScale";
Stage.align("TL");
Stage.addListener(this); // MovieClipインスタンスをリスナーに登録
this.onResize = function() {
   var nStageWidth = Stage.width;
   var nStageHeight = Stage.height;
   this.onEnterFrame = function() {
      var nDistanceX = nStageWidth-this._x;
      var nDistanceY = nStageHeight-this._y;
      if (Math.abs(nDistanceX)<0.5 && Math.abs(nDistanceY)<0.5) {
         this._x = nStageWidth;
         this._y = nStageHeight;
         delete this.onEnterFrame;
      } else {
      this._x += nDistanceX*this.nSpeed;
      this._y += nDistanceY*this.nSpeed;
      }
   };
};

注!ムービークリップの中心点を宮地のサンプルの場合とずらしてお使いください。