Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Сообщения за день
 

Вернуться   Форум Flasher.ru > Блоги > As3 изучение и немного As2

Оценить эту запись

MultiMenu ( horizontal ) ala 2advanced v.5

Запись от in4core размещена 25.01.2012 в 14:46
Обновил(-а) in4core 25.01.2012 в 17:08

Оказалось довольно простой задачей на пару часов, зато выглядит шикарно...

Код AS3:
package com.in4core.navigation 
{
	import com.greensock.TweenMax;
	import flash.display.DisplayObjectContainer;
	import flash.display.Graphics;
	import flash.display.Shape;
	import flash.events.EventDispatcher;
	import flash.events.MouseEvent;
 
	/**
	 * ...
	 * @author in4core lab
	 */
	public class MultiLevelMenu extends EventDispatcher 
	{
		private var _container:DisplayObjectContainer;
		private var _levelsVector:Vector.<LevelContainer> = new Vector.<LevelContainer>;
 
		private namespace utils;
 
		private var _levels:int 		= -1;
		private var _xml:XML 			= null;
		private var _separatorW:int 	= 1;
		private var _separatorH:int 	= 1;
		private var _elementWidth:int 	= 220;
		private var _elementHeight:int 	= 20;
		private var _extra:String 		= '/';
		private var _maskHeight:int     = -1;
 
		public function MultiLevelMenu(container:DisplayObjectContainer , maskHeight:int) {
 
			this._maskHeight = maskHeight;
			this._container = container;
		}
 
		public function generateFromXML ( xml : XML , separatorW:int = 1, separatorH:int = 1 ) : void {
 
			this._separatorH = separatorH;
			this._separatorW = separatorW;
			this._xml = xml;
			this._levels = this.getOpenLevels();
 
			const mask:Shape = new Shape();
			mask.graphics.beginFill(0, 0);
			mask.graphics.drawRect(0, 0, _levels * ( _elementWidth + _separatorW ) , _maskHeight);
			mask.graphics.endFill();
			mask.y = _container.y;
 
			this._container.mask = mask;
			this._container.parent.addChild(mask);
 
			trace('#MultiMenu openLevels : ' + _levels);
 
			this.createContainersToLevels();
 
			this.prepareToOpenLevel(null);
		}
 
		private function createContainersToLevels():void {
 
			for (var i:int = 0; i < _levels ; i++ ) {
 
				const levelContainer:LevelContainer = new LevelContainer();
				const g:Graphics = levelContainer.graphics;
 
				g.beginFill	(0, 0);
				g.drawRect	(0, 0, _elementWidth , _elementHeight);
				g.endFill	();
				levelContainer.x = ( _elementWidth + _separatorW ) * i;
				levelContainer.level = i + 1;
				levelContainer.addEventListener(MouseEvent.MOUSE_MOVE , onMove);
 
				this._container.addChild(levelContainer);
				this._levelsVector.push (levelContainer);
			}
		}
 
		private function onMove(e:MouseEvent):void {
 
			var t:LevelContainer = e.currentTarget as LevelContainer;
			var m:int = _maskHeight;
			var s:int = e.stageY;
			var y:int = _container.y;
 
			if (t.height > m ) t.y = int ( - ( ( t.height - m  ) / m ) * (s - y ) );
		}
 
		private function prepareToOpenLevel(e:MouseEvent):void {
 
			var lst:XMLList = null;
			var link:String = '';
			var level:int = -1;
			var len:int = -1;
 
			if ( ! e ) {
 
				lst = _xml.children();
				level = 0;
			}
 
			else {
 
				const curItem:Item = e.currentTarget as Item;
				const curCont:LevelContainer = curItem.parent as LevelContainer;
				level = curCont.level;
				lst = curItem.subLevels;
				link = curItem.link + _extra;
				this.clearNextLevels(e);
			}
 
			len = lst.length();
 
			const l:LevelContainer = this._levelsVector[level];
 
			if (lst == null || len == 0 ) return;
 
			for (var i:int = 0; i < len; i++) {
 
				const item:Item = new Item( _elementWidth , _elementHeight );
				item.link = link + lst[i].@name;
				item.title = lst[i].@name;
				item.y = ( _elementHeight + _separatorH ) * i;
 
				if ( lst[i].hasComplexContent() ) {
 
					item.subLevels = lst[i].children();
					item.addEventListener(MouseEvent.MOUSE_OVER , prepareToOpenLevel );
					item.showIfSubMenu();
				}
 
				else item.addEventListener(MouseEvent.MOUSE_OVER , clearNextLevels );
 
				item.addEventListener(MouseEvent.CLICK , setLink);
 
				l.addChild ( item );
			}
 
			if(level) TweenMax.fromTo ( l , 0.5 , { y: - l.height } , { y:0 } );
		}
 
		private function setLink(e:MouseEvent):void {
 
			const tar:Item = e.currentTarget as Item;
			this.dispatchEvent( new MultiMenuEvent ( MultiMenuEvent.LINKED , tar.link ) );
		}
 
		private function clearNextLevels(e:MouseEvent):void {
 
			var curItem:Item = e.currentTarget as Item;
			var curCont:LevelContainer = curItem.parent as LevelContainer;
			var level:int = curCont.level;
 
			for (var i:int = level; i < _levelsVector.length; i++) {
 
				this._levelsVector[i].y = 0;
 
				while ( this._levelsVector[i].numChildren ) this._levelsVector[i].removeChildAt(0);
			}
		}
 
 
		private function getOpenLevels():int {
 
			return _xml.@levels;
		}
 
	}
 
}
 
import com.greensock.TweenMax;
import com.in4core.text.DisplayText;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.text.TextField;
 
internal class Item extends Sprite {
 
	private var _title:String;
	private var _link:String;
	private var _sh:Shape = new Shape();
	private var _tf:TextField = DisplayText.addField('f_2', 8, true);
	private var _nx:TextField = DisplayText.addField('f_2', 8, true);
	private var _subLevel:XMLList;
 
	public function Item(w:int , h:int):void {
 
		_sh.graphics.beginFill(0);
		_sh.graphics.drawRect(0, 0, w, h);
		_sh.graphics.endFill();
 
		_tf.textColor = 0xFFFFFF;
		_tf.text = 'test';
		_tf.x = 10;
		_tf.width = w - 20;
		_tf.height = h;
 
		_nx.textColor = 0xFFFFFF;
		_nx.text = '>';
		_nx.width = 10;
		_nx.height = h;
		_nx.x = w - _nx.width - 5;
 
		this.addChild(_sh);
		this.addChild(_tf);
 
		this.mouseChildren = false;
		this.buttonMode = true;
 
		this.addEventListener(MouseEvent.MOUSE_OVER , onOver);
		this.addEventListener(MouseEvent.MOUSE_OUT , onOut);
 
		_sh.alpha = 0.5;
	}
 
	private function onOut(e:MouseEvent):void  {
 
                  TweenMax.to(_sh , 0.5 , { alpha : 0.5 } );
	}
 
	private function onOver(e:MouseEvent):void {
		TweenMax.to(_sh , 0.5 , { alpha : 0.7 } );
	}
 
	public function showIfSubMenu():void {
 
		this.addChild(_nx);
	}
 
	public function set title(n:String):void {
 
		_title = n;
		_tf.text = _title;
	}
 
	public function set subLevels(xmlList:XMLList):void {
 
		_subLevel = xmlList;
	}
 
	public function get title():String {
		return _title;
	}
 
	public function get subLevels():XMLList{
		return _subLevel;
	}
 
	public function get link():String {
		return _link;
	}
 
	public function set link(value:String):void {
		_link = value;
	}
}
 
internal class LevelContainer extends Sprite {
 
	private var _level:int;
 
	public function LevelContainer(  ) {
 
		super();
	}
 
	public function get level():int {
		return _level;
	}
 
	public function set level(value:int):void {
		_level = value;
	}
}
Собственно кастомизацию проводить в интернал Item. Маску для общего контейнера можно бы вынести отдельно без this._container.parent.addChild(mask); такой страшной конструкции, просто решил всю кашу в одном котелке сварить.
Да, и нафига тут неймспейс... а для понта)
На самом деле, писать метод для просчета макс кол-ва нодов мне стало лень, поэтому вынес кол-во уровней в атрибут хмл.

Ну вот получилось под-копирку как у 2A, только на as3. Странно, что в сети, реализаций такого меню я не нашел, может конечно и есть где, хз.
Код:
<?xml version="1.0" encoding="utf-8" ?>
<core levels="4">
	<item name="item1">
		<item name="subitem1"></item>
		<item name="subitem2"></item>
		<item name="subitem8"></item>
		<item name="subitem9"></item>
		<item name="subitem10"></item>
		<item name="subitem11"></item>
		<item name="subitem12"></item>
		<item name="subitem13"></item>
		
	</item>
	<item name="item2"></item>
	<item name="item3"></item>
	<item name="item4"></item>
	<item name="item5">
		<item name="subitem1">
			<item name="SSsubitem4"></item>
			<item name="SSsubitem5"></item>
			<item name="SSsubitem6"></item>
		</item>
		<item name="subitem2">
			<item name="SSsubitem7"></item>
			<item name="SSsubitem8"></item>
			<item name="SSsubitem9"></item>
		</item>
		<item name="subitem3">
			<item name="SSsubitem10"></item>
			<item name="SSsubitem11"></item>
			<item name="SSsubitem12">
				<item name="level4"></item>
				<item name="level4"></item>
				<item name="level4"></item>
				<item name="level4"></item>
				<item name="level4"></item>
				<item name="level4"></item>
				<item name="level4"></item>
			</item>
		</item>
	</item>
</core>
Пощупать что вышло тут , пруф

P.s. для скроллинга использую метод Wolsh всегда и везде, за что ему и огромное спасибо.
Всего комментариев 56

Комментарии

Старый 26.01.2012 15:07 Dima_DPE вне форума
Dima_DPE
@Zebestov это делают 95% современных контролов и в 99% это оправданно. В свете stage3d и новых 2d движков (starling, nd2d и др.) вполне возможно появление контролов, которые не будут наследоваться от Sprite, но даже они не посмеют, чтото добавлять в родителя родитебя

@HardCoder ответ в комменте выше. Лишь добавлю. Вы правы. Я даже больше скажу, удаляться даже объекты с подписаными событиями, но удаляться далеко не сразу и его долго будут висеть в оперативке. А потом по интернету ходят скрины, как флеш банер отожрал всю оперативку и весь процессор. В juick.com точно была
Обновил(-а) Dima_DPE 26.01.2012 в 15:11
Старый 26.01.2012 15:22 in4core вне форума
in4core
 
Аватар для in4core
Код AS3:
Ня
 
Код AS3:
 
var len:int = 0;
var nod:XMLList = xml.item;
while (nod.hasComplexContent()) {
  len++;
  nod = nod.children();
}
Ня

Код AS3:
<?xml version="1.0" encoding="utf-8" ?>
<core levels="4">
	<item name="item1">
		<item name="subitem1"></item>
		<item name="subitem2"></item>
		<item name="subitem8"></item>
		<item name="subitem9"></item>
		<item name="subitem10"></item>
		<item name="subitem11"></item>
		<item name="subitem12"></item>
		<item name="subitem13">
			<item name="item2">
				<item name="item2">
					<item name="item2">
						<item name="item777"></item>
					</item>
				</item>
			</item>
		</item>
 
	</item>
 
</core>
// returns 5 ( когда их 6 )
Потрудились бы хоть проверить, прежде чем что то показывать
Старый 26.01.2012 15:34 Dima_DPE вне форума
Dima_DPE
Виноват, Вместо hasComplexContent лучше проверять length().

Код AS3:
var len:int = 0;
var nod:XMLList = xml.item;
while (nod.length() > 0) {
  len++;
  nod = nod.children();
}
но это не отменяет простоту реализовать этот функционал
Обновил(-а) Dima_DPE 26.01.2012 в 15:36
Старый 26.01.2012 16:25 in4core вне форума
in4core
 
Аватар для in4core
это другое, согласен, больше интересно конечно через e4x )
Старый 26.01.2012 16:41 Dima_DPE вне форума
Dima_DPE
Цитата:
это другое, согласен, больше интересно конечно через e4x )
С ходу в одну строку как узнать глубину не могу придумать, все равно надо в цикле перебирать.
Могу предложить использовать * вместо children
Код AS3:
var len:int = 0;
var nod:XMLList = xml.*;
while (nod.length() > 0) {
  len++;
  nod = nod.*;
}
но не более.
Можно конечно извернутся и загнать все в 2 строки
Код AS3:
var len:int = 0;
var nod:XMLList = new XMLList(xml);
while ((nod = nod.*).length() > 0) len++;
но тут уже начинает ухудшаться читаемость кода
Старый 26.01.2012 16:53 in4core вне форума
in4core
 
Аватар для in4core
Да читаемость падает. Я все таки думал в одну строку можно уложить, жаль
 

 


Часовой пояс GMT +4, время: 02:08.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.