05/24: ドックメニューを作る
Category: ActionScript
Posted by: sato
今回は、Flash MX 2004でドックメニューを作ってみたいと思います。
今回のチュートリアルで、↓こんなメニューが出来ます。
【仕様】
・メニュー項目など外部ファイル(xml)で設定できるようにする
・画像には外部jpgファイルか、外部swfファイルを使用する
・上下左右に向き変更可能
・ステージサイズも変更可能
ライブラリに新規ムービークリップシンボルを追加し、名前・識別子・AS2.0を「dock_menu」とする。
(ActionScriptだけで作成しますので、中身は空のムービークリップです。)
ステージサイズは、幅500、高さ200とする。
フレームレートは、32fpsくらいにする。
タイムライン1フレーム目に以下のActionScriptを記述する。
テキストファイル「dock_menu.as」に以下のActionScriptを記述する。(UTF-8)
解説は、コード内に細かくコメントとして入れてあります。
コメントを含んで100行程度です。
パブリッシュします。
設定ファイルを作ります。
xmlで、メニュー項目やステージサイズなどを設定します。
ファイル名menu.xmlで、下記のようなテキストファイルを作ります。
最初のwholeタグの属性で、各種設定を行い、itemdataタグのitem要素に各メニュー項目のデータを設定します。
以上です。
属性layoutを右側にすると、↓こんな感じになりますので、それに合わせてステージのサイズ、位置を調整して下さい。
縦長にするとサイドメニューとしても使えます。
項目名を表示するなど、まだまだ今後拡張していきたいと思います。
こちらからダウンロードできます。


zipファイル[377clicks]
(ActionScriptファイル、xmlファイル、flaファイル、swfファイルを含むzip圧縮ファイルです。)
今回のチュートリアルで、↓こんなメニューが出来ます。
【仕様】
・メニュー項目など外部ファイル(xml)で設定できるようにする
・画像には外部jpgファイルか、外部swfファイルを使用する
・上下左右に向き変更可能
・ステージサイズも変更可能
手順1
ライブラリに新規ムービークリップシンボルを追加し、名前・識別子・AS2.0を「dock_menu」とする。
(ActionScriptだけで作成しますので、中身は空のムービークリップです。)
ステージサイズは、幅500、高さ200とする。
フレームレートは、32fpsくらいにする。
タイムライン1フレーム目に以下のActionScriptを記述する。
var xml_data = new XML();
//空白を有効にする。
XML.prototype.ignoreWhite = true;
//menu.xmlの場所
_root.xml_path = (_root.xml_path) ? _root.xml_path : "menu.xml";
xml_data.load(_root.xml_path);
xml_data.onLoad = function (loaded) {
if (loaded) {
//xml読み込み完了後の処理
var fc = xml_data.firstChild;
Stage.scaleMode = "noScale";
_root._x += 500 / 2; //中心にもってくる
_root._y += 200 / 2; //中心にもってくる
Stage.width = Number(fc.attributes["swidth"]);
Stage.height = Number(fc.attributes["sheight"]);
_root._x += Number(fc.attributes["xadjust"]);
_root._y += Number(fc.attributes["yadjust"]);
var para = {
layout:fc.attributes["layout"],
i_min:Number(fc.attributes["i_min"]),
i_max:Number(fc.attributes["i_max"]),
i_size:Number(fc.attributes["i_size"]),
inf_wid:Number(fc.attributes["inf_wid"]),
xml_data:xml_data.lastChild
}
dm = attachMovie('dock_menu', 'menu', 1, para);
} else {
_root.createTextField("ititle", 65535, 0, 0, 200, 20);
_root["ititle"].text = "xmlが読み込めませんでした。"+_root.xml_path;
}
}
this.stop();
手順2
テキストファイル「dock_menu.as」に以下のActionScriptを記述する。(UTF-8)
解説は、コード内に細かくコメントとして入れてあります。
コメントを含んで100行程度です。
//──────────────────────────────────
//dock_menu.asc
//──────────────────────────────────
class dock_menu extends MovieClip {
var i_min :Number; //最小サイズ
var i_max :Number; //最大サイズ
var i_size :Number; //元画像のサイズ
var i_sp :Number = 5; //余白
var inf_wid :Number; //マウスの影響範囲
var inf_far :Number = 0; //マウスの影響度合(0~1)
var vary :Number = 0; //inf_farの増減量
var bxm :Number; //前ループのマウス座標
var bym :Number; //前ループのマウス座標
var layout :String; //レイアウト設定
var xml_data :Object; //メニュー項目xml
var node_len :Number; //メニュー項目数
var img_load :Number = 0; //読込済み項目数
var stw :Number; //ステージ横幅
var sth :Number; //ステージ高さ
//──────────────────────────────────
//コンストラクタ
//──────────────────────────────────
function dock_menu(){
//■レイアウト設定
var layout_str:Object = { left:90, top:180, right:270, bottom:0 };
this._rotation = layout_str[this.layout];
//■xml_dataからアイコンを作成
this.node_len = this.xml_data.childNodes.length; //メニュー項目数
//ステージ原点から最初のminアイコンの中心までの長さ
var start_p:Number = (this.node_len - 1) * (this.i_sp + this.i_min) / 2;
for (var i in this.xml_data.childNodes){ //アイコンは中心が原点
this.createEmptyMovieClip(String(i), i + 10);
this[i].createEmptyMovieClip('icon', 1);
this[i].icon.createEmptyMovieClip('g', 1); //回転させるので画像を中心にするため
//画像読込&読込完了したらonEnterFrame開始
this[i].mcl = new MovieClipLoader();
this[i].mcl_listener = new Object();
this[i].mcl_listener.dock = this; //mcl_listenerからdock_menuにアクセスするため
this[i].mcl.addListener(this[i].mcl_listener);
this[i].mcl.loadClip(this.xml_data.childNodes[i].attributes["img_url"], this[i].icon.g);
this[i].mcl_listener.onLoadComplete = function(){
this.dock.img_load++;
if (this.dock.img_load == this.dock.node_len){ this.dock.onEnterFrame = this.dock.ef; }
}
this[i].icon.g._x = -this.i_size / 2; //x原点を中心に
this[i].icon.g._y = -this.i_size / 2; //y原点を下に
this[i].icon._rotation = -this._rotation; //回転角度
this[i].icon._y = -this.i_size / 2; //y原点を下に
this[i]._x = i * (this.i_min + this.i_sp) - start_p; //初期位置
this[i].bx = this[i]._x; //初期位置を確保
this[i]._y = -this.i_sp; //余白分ずらす
//クリックイベント
this[i].onPress = function(){ getURL(_parent.xml_data.childNodes[i].attributes["get_url"]); }
}
//トレイ作成
var h:Number = this.i_min + this.i_sp * 2;
var tray:MovieClip = this.createEmptyMovieClip('tray', 1);
tray.lineStyle(0, 0xcccccc, 100);
tray.beginFill( 0xeeeeee, 100);
tray.lineTo(0, -h); tray.lineTo(100, -h); tray.lineTo(100, 0); tray.lineTo(0, 0);
tray.endFill();
}
//──────────────────────────────────
//EnterFrame
//──────────────────────────────────
function ef(){
//マウスに動きなし&inf_farが0か1なら処理しない(CPU負荷軽減)
if((this.bxm == this._xmouse) && (this.bym == this._ymouse) && ((this.inf_far == 0) || (this.inf_far == 1))) { return false; }
this.bxm = (this.bxm == undefined) ? 0 : this._xmouse; //トレイ初期幅を正常にするため
this.bym = this._ymouse; //画像読込完了待ちをしないと無理かも
//----------inf_farの設定
//varyが0なら、0.2か-0.2にする
if (this.vary ==0){
//マウスが影響範囲内かどうかの判定(一番高いところより下で、底辺より上で、トレイの左右端より内側)
this.vary = (this.bym > (this.i_min - this.i_max) * this.inf_far - (2 * this.i_sp) - this.i_min)
&& (this.bym < 0) && (this.bxm > tray_l()) && (this.bxm < tray_r()) ? 0.2 : -0.2;
}
this.inf_far += this.vary; //inf_far増減
if (this.inf_far < 0.01 || this.inf_far > 0.99) { this.vary = 0; } //inf_farが変化不要なら、vary = 0
this.inf_far = Math.min(1, Math.max(0, this.inf_far)); //inf_farを0 ~ 1 にする
//----------inf_farの設定ここまで
//個々のアイコンの位置と大きさを計算
//各アイコンの倍率は「中心からのマウスのズレ」で計算する
//その結果に「アイコンへの影響度合inf_far」をかけている
for (var i in this.xml_data.childNodes){
//dx ・・・ 有効範囲での、初期位置とマウスの差(-this.inf_wid ~ this.inf_wid)
var dx :Number = Math.min(Math.max(this[i].bx - this.bxm, -this.inf_wid), this.inf_wid);
var i_gap :Number = this.i_max - this.i_min; //maxとminの差
var dx_cos :Number = Math.cos(1.57 * (dx / this.inf_wid)); //1.57 = ラジアン四半周
var dx_sin :Number = Math.sin(1.00 * (dx / this.inf_wid)); //1.57 = ラジアン四半周
var dim :Number = i_gap * (dx_cos * this.inf_far) + this.i_min; //maxとminの差*倍率 + min
this[i]._x = (i_max + i_sp * 2) * (dx_sin * this.inf_far) + this[i].bx; //間隔 *倍率 + 初期位置
this[i]._xscale = 100 * dim / this.i_size; //アイコン倍率
this[i]._yscale = 100 * dim / this.i_size;
}
//トレーをリサイズ
this['tray']._x = tray_l();
this['tray']._width = tray_r() - this['tray']._x;
}
//──────────────────────────────────
//トレイの両端計算
//──────────────────────────────────
function tray_l(){ return this[ 0]._x - this[ 0]._width / 2 - this.i_sp; }
function tray_r(){ return this[this.node_len - 1]._x + this[this.node_len - 1]._width / 2 + this.i_sp; }
}
パブリッシュします。
手順3
設定ファイルを作ります。
xmlで、メニュー項目やステージサイズなどを設定します。
ファイル名menu.xmlで、下記のようなテキストファイルを作ります。
<?xml version="1.0" encoding="UTF-8"?>
<whole
layout = "bottom"
i_min = "32"
i_max = "128"
i_size = "128"
inf_wid = "60"
swidth = "800"
sheight = "250"
xadjust = "0"
yadjust = "50">
</whole>
<itemdata>
<item img_url="http://wa.otesei.com/media/as/as_logo.swf"
get_url="http://as.otesei.com/"></item>
<item img_url="http://wa.otesei.com/media/as/fplayer.swf"
get_url="http://wa.otesei.com/"></item>
<item img_url="http://wa.otesei.com/media/as/firefox.jpg"
get_url="http://wa.otesei.com/"></item>
<item img_url="http://wa.otesei.com/media/as/icon.swf"
get_url="http://wa.otesei.com/"></item>
<item img_url="http://wa.otesei.com/media/as/adobe.jpg"
get_url="http://wa.otesei.com/"></item>
</itemdata>
最初のwholeタグの属性で、各種設定を行い、itemdataタグのitem要素に各メニュー項目のデータを設定します。
| layout = "bottom" | top=上側、bottom=下側、left=左側、right=右側 |
| i_min = "32" | 画像縮小時のサイズ |
| i_max = "128" | 画像拡大時のサイズ |
| i_size = "128" | 元画像のサイズ |
| inf_wid = "60" | マウスに反応する範囲 |
| swidth = "800" | Flashのステージサイズ |
| sheight = "250" | Flashのステージサイズ |
| xadjust = "0" | ステージの調整(x座標を指定分ずらす) |
| yadjust = "50" | ステージの調整(x座標を指定分ずらす) |
以上です。
属性layoutを右側にすると、↓こんな感じになりますので、それに合わせてステージのサイズ、位置を調整して下さい。
<whole
layout = "left"
i_min = "32"
i_max = "128"
i_size = "128"
inf_wid = "60"
swidth = "200"
sheight = "500"
xadjust = "-100"
yadjust = "0">
</whole>
<itemdata>
縦長にするとサイドメニューとしても使えます。
項目名を表示するなど、まだまだ今後拡張していきたいと思います。
こちらからダウンロードできます。



zipファイル[377clicks](ActionScriptファイル、xmlファイル、flaファイル、swfファイルを含むzip圧縮ファイルです。)