ActionScript 3.0 实现树形菜单。
转自:http://www.cppblog.com/twzheng/archive/2007/10/19/34598.aspx
主要2个类:给了我不少启发.打算修改成xml,并加上拖动节点,添加删除节点,更名节点的功能.
Flash ActionScript 3.0 实现的树形菜单
这是我初学ActionScript 3.0时实现的treeMenu类, 贴出来分享,或许对ActionScript 3.0的初学者有一定的帮助,但不建议在应用程序开发中使用。
各位博友可以就此发表自己的观点,谢谢各位指教。
下面是treeMenu类的定义:
/**
* treeMenu类
*
* 构造一个树形菜单
*
* @author twzheng (http://www.ugocn.com)
* @date 20070903
* @version 1.0.070903
*
*/
////////////////////////////////////////////////////////////////////////////////////////////
// 在这里添加修改说明:
//
//
////////////////////////////////////////////////////////////////////////////////////////////
package com.components
{
import flash.display.MovieClip;
public class treeMenu extends MovieClip
{
public var rootMenu:menuItem;
function treeMenu()
{
}
public function newTreeMenu()
{
if(rootMenu != null)
{
trace(" 错误:根菜单已存在,根菜单只能有一个!");
return;
}
rootMenu = new menuItem("rootMenu","rootMenu");
if(rootMenu == null)
{
trace(" 创建根菜单失败!");
return;
}
rootMenu.removeChild(rootMenu.menuLabel);
rootMenu.childMenu.x = 0;
rootMenu.childMenu.y = 0;
this.addChild(rootMenu);
}
public function addChildMenu(bMenu:menuItem, mName:String, mLabel:String)
{
var mItem = new menuItem(mName,mLabel);
if(mItem == null) return;
var index:int = bMenu.childItem.length;
mItem.y = menuItemLocalizer(bMenu.childItem);
bMenu.childItem[index] = mItem;
bMenu.childMenu.addChild(mItem);
}
private function menuItemLocalizer(bMenu:Array):int
{
var num:int = 0;
for each (var item in bMenu)
num = num + item.getHeight();
return num;
}
}
}
/**
* 菜单项节点类
*
* @author twzheng (http://www.ugocn.com)
* @date 20070903
* @version 1.0.070903
*/
import flash.display.DisplayObjectContainer;
import flash.display.MovieClip;
import flash.text.TextField;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.ui.Mouse;
internal class menuItem extends MovieClip
{
public var menuName:String; // 菜单项名称
public var menuLabel:TextField; // 菜单项标签(即显示给用户的菜单标签)
public var childMenu:DisplayObjectContainer; // 子菜单项容器
public var childItem:Array; // 子菜单项数组
private var h:Number; // 菜单项高度属性,记录的是实际高度(包含隐藏菜单高度)
function menuItem(mName:String, mLabel:String)
{
if(mName == "" || mName == null || mLabel == null)
{
trace(" 菜单名或者菜单标签为空,添加菜单项失败!");
return;
}
menuName = mName;
menuLabel = new TextField();
menuLabel.text = mLabel;
menuLabel.height = 22;
menuLabel.textColor = 0x000000;
menuLabel.background = false;
menuLabel.addEventListener(MouseEvent.MOUSE_MOVE,itemMouseMove);
menuLabel.addEventListener(MouseEvent.MOUSE_OUT,itemMouseOut);
this.addChild(menuLabel);
childMenu = new MovieClip();
childMenu.addEventListener(Event.ADDED,mcAddedEvent);
childMenu.addEventListener(Event.REMOVED,mcRemovedEvent);
this.childMenu.x = this.menuLabel.x + 8;
this.childMenu.y = this.menuLabel.y + this.menuLabel.height;
this.addChild(childMenu);
childItem = new Array();
this.h = menuLabel.height;
// 菜单项单击事件应留给外部使用者实现
//this.menuLabel.addEventListener(MouseEvent.CLICK,itemClick);
}
// 返回菜单项显示的真实高度,即菜单项的实际高度减去隐藏菜单项的高度
public function getHeight():Number
{
return h - getHideMenu(this);
}
/**
* 获取item的childMenu中所有隐藏子菜单项的高度和
*
* @item 主菜单项,此函数即计算它的子菜单中隐藏菜单的高度
* @return 返回item的childMenu中visible属性为false的子菜单高度和
*
* 注:如果item.childMenu的visible属性为false即返回childMenu的高度,如果item.childMenu为空则返回0。
*/
private function getHideMenu(item:menuItem):Number
{
var sumHeight = 0;
if(item.childMenu.visible)
{
if(item.childItem == null)
return 0;
for(var i = 0; i < item.childItem.length; i++)
{
// 对每个子菜单项递归
sumHeight = sumHeight + getHideMenu(item.childItem[i]);
}
return sumHeight;
}
else
return item.childMenu.height;
}
/**
* 获取名字为mName菜单项的对象
*
* @mName 菜单项名字字符串
* @return 返回调用此函数的菜单项的子菜单中名字为mName的子菜单项对象
*/
public function getMenu(mName:String):menuItem
{
for each(var item in childItem)
{
if(item.menuName == mName)
return item;
}
trace(" 错误:不存在名为 " + mName + " 的子菜单项!");
return null;
}
/**
* 接收TextField的单击事件,更改TextField对应item的子菜单显示状态
*
* @item 接收到单击事件的menuLabel对应的菜单项(menuItem)
*/
public function chgChildItemVisible(item:menuItem)
{
var chgHeight = 0;
if(item.childMenu.visible)
{
chgHeight = item.getHeight() - item.menuLabel.height;
item.childMenu.visible = false;
updateMenu(item,0 - chgHeight);
}
else
{
item.childMenu.visible = true;
chgHeight = item.childMenu.height - getHideMenu(item);
updateMenu(item,chgHeight);
}
}
/**
* 更新各菜单项位置
* 注:由于参数item的子菜单容器childMenu高度发生变化而需要改变其同级别的菜单项以及所有的父菜单项的y坐标
*
* @item 引发调用此函数的菜单项(即由于item的childMenu高度改变而需要调用此函数)
* @chgHeight 需要改变的y坐标高度,正值即增加y坐标值,负值减小y坐标值
*/
private function updateMenu(item:menuItem, chgHeight:Number)
{
if(item == null) return;
// item.parent为父菜单的子菜单容器,item.parent.paren才是对应的父菜单项
var parentItem = item.parent.parent;
var i,index:int = 0;
if(parentItem == null || ! (parentItem is menuItem))
return;
// 搜索item在父菜单的子菜单数组childItem中的索引
index = parentItem.childItem.indexOf(item);
// 改变item同级别的并且位于其后的菜单项的显示位置
for(i = index + 1; i < parentItem.childItem.length; i++)
{
parentItem.childItem[i].y = parentItem.childItem[i].y + chgHeight;
}
// 对父菜单项递归
updateMenu(parentItem,chgHeight);
}
// private function itemClick(e:MouseEvent)
// {
// var item = e.currentTarget;
// chgChildItemVisible(item.parent);
// }
private function itemMouseMove(e:MouseEvent)
{
var item = e.currentTarget;
item.background = true;
item.backgroundColor = 0x66ccFF;
item.textColor = 0x0000FF;
}
private function itemMouseOut(e:MouseEvent)
{
var item = e.currentTarget;
item.background = false;
item.backgroundColor = 0xFFFFFF;
item.textColor = 0x000000;
}
// 向子菜单容器加入子菜单项事件,增加当前菜单的高度
private function mcAddedEvent(e:Event)
{// 此事件响应函数还需要更改。。。
var mc = e.currentTarget;
h = h + 22;//mc.height;///2
}
// 从子菜单容器移除子菜单项事件,减小当前菜单的高度
private function mcRemovedEvent(e:Event)
{// 此事件响应函数还需要更改。。。
var mc = e.currentTarget;
h = h - 22;//mc.height/2;
}
}
* treeMenu类
*
* 构造一个树形菜单
*
* @author twzheng (http://www.ugocn.com)
* @date 20070903
* @version 1.0.070903
*
*/
////////////////////////////////////////////////////////////////////////////////////////////
// 在这里添加修改说明:
//
//
////////////////////////////////////////////////////////////////////////////////////////////
package com.components
{
import flash.display.MovieClip;
public class treeMenu extends MovieClip
{
public var rootMenu:menuItem;
function treeMenu()
{
}
public function newTreeMenu()
{
if(rootMenu != null)
{
trace(" 错误:根菜单已存在,根菜单只能有一个!");
return;
}
rootMenu = new menuItem("rootMenu","rootMenu");
if(rootMenu == null)
{
trace(" 创建根菜单失败!");
return;
}
rootMenu.removeChild(rootMenu.menuLabel);
rootMenu.childMenu.x = 0;
rootMenu.childMenu.y = 0;
this.addChild(rootMenu);
}
public function addChildMenu(bMenu:menuItem, mName:String, mLabel:String)
{
var mItem = new menuItem(mName,mLabel);
if(mItem == null) return;
var index:int = bMenu.childItem.length;
mItem.y = menuItemLocalizer(bMenu.childItem);
bMenu.childItem[index] = mItem;
bMenu.childMenu.addChild(mItem);
}
private function menuItemLocalizer(bMenu:Array):int
{
var num:int = 0;
for each (var item in bMenu)
num = num + item.getHeight();
return num;
}
}
}
/**
* 菜单项节点类
*
* @author twzheng (http://www.ugocn.com)
* @date 20070903
* @version 1.0.070903
*/
import flash.display.DisplayObjectContainer;
import flash.display.MovieClip;
import flash.text.TextField;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.ui.Mouse;
internal class menuItem extends MovieClip
{
public var menuName:String; // 菜单项名称
public var menuLabel:TextField; // 菜单项标签(即显示给用户的菜单标签)
public var childMenu:DisplayObjectContainer; // 子菜单项容器
public var childItem:Array; // 子菜单项数组
private var h:Number; // 菜单项高度属性,记录的是实际高度(包含隐藏菜单高度)
function menuItem(mName:String, mLabel:String)
{
if(mName == "" || mName == null || mLabel == null)
{
trace(" 菜单名或者菜单标签为空,添加菜单项失败!");
return;
}
menuName = mName;
menuLabel = new TextField();
menuLabel.text = mLabel;
menuLabel.height = 22;
menuLabel.textColor = 0x000000;
menuLabel.background = false;
menuLabel.addEventListener(MouseEvent.MOUSE_MOVE,itemMouseMove);
menuLabel.addEventListener(MouseEvent.MOUSE_OUT,itemMouseOut);
this.addChild(menuLabel);
childMenu = new MovieClip();
childMenu.addEventListener(Event.ADDED,mcAddedEvent);
childMenu.addEventListener(Event.REMOVED,mcRemovedEvent);
this.childMenu.x = this.menuLabel.x + 8;
this.childMenu.y = this.menuLabel.y + this.menuLabel.height;
this.addChild(childMenu);
childItem = new Array();
this.h = menuLabel.height;
// 菜单项单击事件应留给外部使用者实现
//this.menuLabel.addEventListener(MouseEvent.CLICK,itemClick);
}
// 返回菜单项显示的真实高度,即菜单项的实际高度减去隐藏菜单项的高度
public function getHeight():Number
{
return h - getHideMenu(this);
}
/**
* 获取item的childMenu中所有隐藏子菜单项的高度和
*
* @item 主菜单项,此函数即计算它的子菜单中隐藏菜单的高度
* @return 返回item的childMenu中visible属性为false的子菜单高度和
*
* 注:如果item.childMenu的visible属性为false即返回childMenu的高度,如果item.childMenu为空则返回0。
*/
private function getHideMenu(item:menuItem):Number
{
var sumHeight = 0;
if(item.childMenu.visible)
{
if(item.childItem == null)
return 0;
for(var i = 0; i < item.childItem.length; i++)
{
// 对每个子菜单项递归
sumHeight = sumHeight + getHideMenu(item.childItem[i]);
}
return sumHeight;
}
else
return item.childMenu.height;
}
/**
* 获取名字为mName菜单项的对象
*
* @mName 菜单项名字字符串
* @return 返回调用此函数的菜单项的子菜单中名字为mName的子菜单项对象
*/
public function getMenu(mName:String):menuItem
{
for each(var item in childItem)
{
if(item.menuName == mName)
return item;
}
trace(" 错误:不存在名为 " + mName + " 的子菜单项!");
return null;
}
/**
* 接收TextField的单击事件,更改TextField对应item的子菜单显示状态
*
* @item 接收到单击事件的menuLabel对应的菜单项(menuItem)
*/
public function chgChildItemVisible(item:menuItem)
{
var chgHeight = 0;
if(item.childMenu.visible)
{
chgHeight = item.getHeight() - item.menuLabel.height;
item.childMenu.visible = false;
updateMenu(item,0 - chgHeight);
}
else
{
item.childMenu.visible = true;
chgHeight = item.childMenu.height - getHideMenu(item);
updateMenu(item,chgHeight);
}
}
/**
* 更新各菜单项位置
* 注:由于参数item的子菜单容器childMenu高度发生变化而需要改变其同级别的菜单项以及所有的父菜单项的y坐标
*
* @item 引发调用此函数的菜单项(即由于item的childMenu高度改变而需要调用此函数)
* @chgHeight 需要改变的y坐标高度,正值即增加y坐标值,负值减小y坐标值
*/
private function updateMenu(item:menuItem, chgHeight:Number)
{
if(item == null) return;
// item.parent为父菜单的子菜单容器,item.parent.paren才是对应的父菜单项
var parentItem = item.parent.parent;
var i,index:int = 0;
if(parentItem == null || ! (parentItem is menuItem))
return;
// 搜索item在父菜单的子菜单数组childItem中的索引
index = parentItem.childItem.indexOf(item);
// 改变item同级别的并且位于其后的菜单项的显示位置
for(i = index + 1; i < parentItem.childItem.length; i++)
{
parentItem.childItem[i].y = parentItem.childItem[i].y + chgHeight;
}
// 对父菜单项递归
updateMenu(parentItem,chgHeight);
}
// private function itemClick(e:MouseEvent)
// {
// var item = e.currentTarget;
// chgChildItemVisible(item.parent);
// }
private function itemMouseMove(e:MouseEvent)
{
var item = e.currentTarget;
item.background = true;
item.backgroundColor = 0x66ccFF;
item.textColor = 0x0000FF;
}
private function itemMouseOut(e:MouseEvent)
{
var item = e.currentTarget;
item.background = false;
item.backgroundColor = 0xFFFFFF;
item.textColor = 0x000000;
}
// 向子菜单容器加入子菜单项事件,增加当前菜单的高度
private function mcAddedEvent(e:Event)
{// 此事件响应函数还需要更改。。。
var mc = e.currentTarget;
h = h + 22;//mc.height;///2
}
// 从子菜单容器移除子菜单项事件,减小当前菜单的高度
private function mcRemovedEvent(e:Event)
{// 此事件响应函数还需要更改。。。
var mc = e.currentTarget;
h = h - 22;//mc.height/2;
}
}
treeMenu类简单应用
package
{
import flash.display.MovieClip;
import flash.events.*;
import com.library.treeMenu;
public class menu extends MovieClip
{
function menu()
{
var tm = new treeMenu();
tm.newTreeMenu(); // 创建根菜单
tm.addChildMenu(tm.rootMenu,"基菜单-01","基菜单-01");
tm.rootMenu.getMenu("基菜单-01").menuLabel.addEventListener(MouseEvent.CLICK,eventClick);
tm.addChildMenu(tm.rootMenu.getMenu("基菜单-01"),"一级菜单-011","一级菜单-011");
tm.addChildMenu(tm.rootMenu,"基菜单-02","基菜单-02");
tm.rootMenu.getMenu("基菜单-02").menuLabel.addEventListener(MouseEvent.CLICK,eventClick);
tm.addChildMenu(tm.rootMenu.getMenu("基菜单-02"),"一级菜单-021","一级菜单-021");
tm.rootMenu.getMenu("基菜单-02").getMenu("一级菜单-021").menuLabel.addEventListener(MouseEvent.CLICK,eventClick);
tm.addChildMenu(tm.rootMenu.getMenu("基菜单-02").getMenu("一级菜单-021"),"二级菜单-0211","二级菜单-0211");
tm.rootMenu.getMenu("基菜单-02").getMenu("一级菜单-021").getMenu("二级菜单-0211").menuLabel.addEventListener(MouseEvent.CLICK,eventClick);
tm.addChildMenu(tm.rootMenu.getMenu("基菜单-02").getMenu("一级菜单-021").getMenu("二级菜单-0211"),"三级菜单-02111","三级菜单-02111");
tm.addChildMenu(tm.rootMenu,"基菜单-03","基菜单-03");
// 菜单坐标 默认坐标(0,0)
//tm.x = 50;
//tm.y = 50;
this.addChild(tm);
}
private function eventClick(e:MouseEvent)
{
var item = e.currentTarget;
item.parent.chgChildItemVisible(item.parent); // 隐藏或显示子菜单项
}
}
}
{
import flash.display.MovieClip;
import flash.events.*;
import com.library.treeMenu;
public class menu extends MovieClip
{
function menu()
{
var tm = new treeMenu();
tm.newTreeMenu(); // 创建根菜单
tm.addChildMenu(tm.rootMenu,"基菜单-01","基菜单-01");
tm.rootMenu.getMenu("基菜单-01").menuLabel.addEventListener(MouseEvent.CLICK,eventClick);
tm.addChildMenu(tm.rootMenu.getMenu("基菜单-01"),"一级菜单-011","一级菜单-011");
tm.addChildMenu(tm.rootMenu,"基菜单-02","基菜单-02");
tm.rootMenu.getMenu("基菜单-02").menuLabel.addEventListener(MouseEvent.CLICK,eventClick);
tm.addChildMenu(tm.rootMenu.getMenu("基菜单-02"),"一级菜单-021","一级菜单-021");
tm.rootMenu.getMenu("基菜单-02").getMenu("一级菜单-021").menuLabel.addEventListener(MouseEvent.CLICK,eventClick);
tm.addChildMenu(tm.rootMenu.getMenu("基菜单-02").getMenu("一级菜单-021"),"二级菜单-0211","二级菜单-0211");
tm.rootMenu.getMenu("基菜单-02").getMenu("一级菜单-021").getMenu("二级菜单-0211").menuLabel.addEventListener(MouseEvent.CLICK,eventClick);
tm.addChildMenu(tm.rootMenu.getMenu("基菜单-02").getMenu("一级菜单-021").getMenu("二级菜单-0211"),"三级菜单-02111","三级菜单-02111");
tm.addChildMenu(tm.rootMenu,"基菜单-03","基菜单-03");
// 菜单坐标 默认坐标(0,0)
//tm.x = 50;
//tm.y = 50;
this.addChild(tm);
}
private function eventClick(e:MouseEvent)
{
var item = e.currentTarget;
item.parent.chgChildItemVisible(item.parent); // 隐藏或显示子菜单项
}
}
}