Jump to content
GreenSock

viebone

liquid / organic menu

Recommended Posts

Hi there,

 

I am in a new project and I would like to display in the home an organic menu.

 

My idea is to have four big squares as buttons, each one with a diferent color, and if you put your mouse over one, this one will grow with a elastic movement, and the others will contract with the same elastic motion. Like fluids or liquids.

 

Could any one put me on the way? how can I achive that? any ideas?

 

Thanks very much for your time.

Link to comment
Share on other sites

Do you have an example of what this would look like? There are lots of variables, like:

 

1) How will the squares be arranged? Side-by-side horizontally? Two-by-two making a larger square?

 

2) Will there be space between the boxes and will that spacing need to remain consistent?

 

3) As the boxes grow/shrink, will they slide around to make room for each other?

 

Pretty much anything is possible, but some things are much more complex than others.

 

This forum isn't generally for "tell me how to build this whole thing" questions, so you may not get the answer you're after, but if you have some specific questions about tweening or any of the GreenSock stuff, definitely post 'em here.

Link to comment
Share on other sites

Thanks for your answer!

 

You are right, my question is very general, i ask in the forum because maybe others readers did something similar in the past.

 

The squares will be arranged Side-by-side vertically, without space between boxes and when the targeted box increase its wide, the others contract to let space.

 

My problem is how can I make it looks liquid or organic. I already have the layout and It does the same movement but without "organic" look, I have a linear animation.

 

Thanks a lot

Link to comment
Share on other sites

Hi

 

Keep in mind that this is a general idea, I don't know how you have your project structured, but I would simply create mouse event listeners to mouse entering and leaving the button. The mouse would need to keep the instance of the tween created and null it when the tween finished. Idea is:

 

1. On mouse enter, check if tween exists, if so make it change direction, if not start a new tween to grow.

2. On mouse leave, check if tween exists, if so make it change direction, if not start a new tween to shrink.

3. On tween complete, null the tween variable.

 

I'm not completely sure how to change the tween direction to be honest but I'm pretty sure it is possible.

Link to comment
Share on other sites

I got it.

 

Now i am fighting on how the "neighbors" react to the grow of the targeted button.

 

Thanks.

Link to comment
Share on other sites

An array with all the neighbors. When you trigger the event on the button to grow, call a method passing the current button as a parameter. In the function do something like...

 

if(buttonPassed != buttonArray[buttonToTest]) buttonArray[buttonToTest].shrink()

 

This is very... erm... untested to say the least, but it should get you running. Keep in mind that to make something very organic, a lot of tweaking is needed. The trick is to get the details just right.

Link to comment
Share on other sites

hello,

 

If someone is interested, this is what I could achieve: http://www.framestorm.tv/user/saisa/

 

Thanks

 

 

 

public class BodyUI extends Sprite implements IResizable

{

	//Main vars

	public static var _instance:BodyUI;

	public var bg:Sprite;

	private var _parent:Sprite;



	//Home Main Buttons

	private var mainHomeButton:HomeButton;

	private var pointer:Pointer;

	private var mainButtonsNum:Number = 4;

	private var buttonWidth:Number;

	private var mainButtonsArr:Array = new Array();

	private var mainButtonsCreated:Boolean = false;

	private var buttonColors:Array = new Array(0xFFFF00, 0x00FF00, 0x0000FF, 0xFF00FF);

	private var shrink:Number;

	private var growthFactor:Number = 0.40;

	private var scaleFactor:Number = 1 + growthFactor;



	//Size vars

	private var w:Number;

	private var h:Number;



	public function BodyUI(p:Sprite) 

	{

		//FlashConnect.trace(""+p);

		_parent = p;

		bg = new BodyBG ();

		addChild (bg);



		//Create main buttons

		for (var x:Number = 0; x < mainButtonsNum; x++)

		{

			mainHomeButton = new HomeButton();

			pointer = new Pointer();

			mainHomeButton.id = x + 1;

			mainHomeButton.addEventListener(MouseEvent.MOUSE_OVER, overButtonEvent);

			mainHomeButton.addEventListener(MouseEvent.MOUSE_OUT, outButtonEvent);

			TweenLite.to(mainHomeButton, 0, { tint:buttonColors[x] } );

			mainHomeButton.alpha = 0.5;

			mainButtonsArr.push(mainHomeButton);

		}

	}



	public static function getInstance (p:Sprite):BodyUI

	{

		if (_instance == null)

		_instance = new BodyUI (p);

		return _instance;

	}



	public function setSize(w:Number, h:Number):void

	{

		bg.width = w;

		bg.height = h;



		this.w = w;

		this.h = h;



		buttonWidth = w / mainButtonsNum;



		placeMainButtons();

	}



	private function placeMainButtons():void

	{

		for (var x:Number = 0; x < mainButtonsArr.length; x++)

		{

			//Global to local

			var _target:HomeButton = mainButtonsArr[x];



			//Set size and xy positions

			_target.setSize(buttonWidth, h);

			_target.x = (buttonWidth * x) + buttonWidth/2;

			_target.y = h/2;



			addChild(_target);

		}

			//addChild(pointer);

	}



	private function overButtonEvent(e:MouseEvent):void

	{

		var _tar:Object = e.currentTarget;

		var _id:Number = _tar.id;



		//check if its the first button

		if (_id == 1)

		{

			//Launching the function indicating that the first button is targeted. 

			organicButtonsMov("first",_tar)

		}



		if (_id > 1 && _id < mainButtonsNum)

		{

			//Launching the function indicating that one buttonween buttons was targeted. 

			organicButtonsMov("between",_tar)

		}



		if (_id == mainButtonsNum)

		{

			//Launching the function indicating that the lastone button was targeted. 

			organicButtonsMov("last",_tar)

		}



	}



	private function outButtonEvent(e:MouseEvent):void

	{

		var _tar:Object = e.currentTarget;

		var _id:Number = _tar.id;

		//add a tween



		for (var x:Number = 0; x < mainButtonsArr.length; x++)

		{

			var _w:Number = w / mainButtonsNum;

			var _w2:Number = (_w * x) + _w/2;



			TweenLite.to(mainButtonsArr[x], 1, {x:_w2,scaleX:1, ease:Elastic.easeOut} );

		}

	}



	private function organicButtonsMov(which:String,tar:Object):void

	{

		var _tar:Object = tar

		var _id:Number = _tar.id;



		//Lateral amount of pixels to move

		var lateralMov:Number;

		//the newWidth of the targeted button

		var newWidth:Number;



		//The new area width available for the others buttons

		var newArea:Number;



		//the newWidth for the shrunk button

		var newShrunkWide:Number;



		//To know how much we have to shrink each button

		var shrinkFactor:Number;



		var xPos:Number;

		var ini:Number;

		var shrunkButtonsXPos:Number;

		var counter1:Number;

		var counter2:Number;

		var counter3:Number;

		var myTween:TweenLite;



		switch(which)

		{

			case "first":

			newArea = w - (buttonWidth + (buttonWidth * growthFactor));

			newShrunkWide = newArea / (mainButtonsNum - 1);

			shrinkFactor = (1 - (growthFactor / (mainButtonsNum - 1)));

			lateralMov = buttonWidth * growthFactor / 2;

			newWidth = buttonWidth + (buttonWidth * growthFactor);

			//To count each time a shrunk button is transform

			counter1 = 0;

			//Loop over the buttons array

			for (var x:Number = 0; x < mainButtonsArr.length; x++)

			{

				//Check if it is the targeted button or not

				if (mainButtonsArr[x].id != _id)

				{

				//If not, shrink the button



					//The 0 point of the new area once the first button have growth

					ini = newWidth + (newShrunkWide / 2);

					//The new position of the shrunk buttons

					shrunkButtonsXPos = ini + (newShrunkWide * counter1);

					//Add 1 to the counter

					counter1 ++;

					TweenLite.to(mainButtonsArr[x], 1, { x:shrunkButtonsXPos, width:newShrunkWide, ease:Elastic.easeOut } );

				}else {

				//If it is, transform the wide of the button

					//The new xpos for the targeted button

					xPos = buttonWidth/2 + lateralMov;

					TweenLite.to(_tar, 1, { scaleX:scaleFactor, x: xPos, ease:Elastic.easeOut } );

				}

			}

			break;



			case "between":



			//To count each time a shrunk button is transform

			counter2 = 0;

			counter3 = 0;

			for (var y:Number = 0; y < mainButtonsNum; y++)

			{

				var temp:Object = mainButtonsArr[y];

				if (temp.id < _id)

				{

					newArea = _tar.x - ((buttonWidth + (buttonWidth * growthFactor)) / 2);

					ini = 0;

					newShrunkWide = newArea / (_id - 1);

					//FlashConnect.trace("newShrunkWide: " + (_id - 1));

					shrunkButtonsXPos = (newShrunkWide * counter2) + (newShrunkWide/2);

					TweenLite.to(temp, 1, { x:shrunkButtonsXPos, width:newShrunkWide, ease:Elastic.easeOut  } );

					counter2++;

				}

				if (temp.id == _id)

				{



					TweenLite.to(temp, 1, {scaleX:scaleFactor, ease:Elastic.easeOut } );



				}

				if (temp.id >_id)

				{

					newArea = w - (_tar.x + (buttonWidth + (buttonWidth*growthFactor))/2);

					newShrunkWide = newArea / (mainButtonsNum - _id);

					ini = _tar.x + (buttonWidth + (buttonWidth*growthFactor))/2;



					shrunkButtonsXPos = ini + ((newShrunkWide*counter3)+newShrunkWide/2);

					//pointer.x = ini;

					//pointer.y = temp.y - temp.height / 2;

					TweenLite.to(temp, 1, { x:shrunkButtonsXPos, width:newShrunkWide, ease:Elastic.easeOut } );

					counter3++;

				}



			}

			break;



			case "last":

				newArea = w - (buttonWidth + (buttonWidth * growthFactor));

				newShrunkWide = newArea / (mainButtonsNum - 1);

				shrinkFactor = (1 - (growthFactor / (mainButtonsNum - 1)));

				lateralMov = buttonWidth * growthFactor / 2;

				newWidth = buttonWidth + (buttonWidth * growthFactor);

				//To count each time a shrunk button is transform

				counter3 = 0;

				//Loop over the buttons array

				for (var z:Number = 0; z < mainButtonsArr.length; z++)

				{

					//Check if it is the targeted button or not

					if (mainButtonsArr[z].id != _id)

					{

					//If not, shrink the button



						//The 0 point of the new area once the first button have growth

						ini = newShrunkWide/2;

						//The new position of the shrunk buttons

						shrunkButtonsXPos = ini + (newShrunkWide * counter3);

						//Add 1 to the counter

						//pointer.x = ini;

						//pointer.y = temp.y - temp.height / 2;

						TweenLite.to(mainButtonsArr[z], 1, { x:shrunkButtonsXPos, width:newShrunkWide, ease:Elastic.easeOut } );

						counter3 ++;

					}else {

					//If it is, transform the wide of the button

						//The new xpos for the targeted button

						xPos = (w-buttonWidth/2) - lateralMov;



						TweenLite.to(_tar, 1, { scaleX:scaleFactor, x: xPos, ease:Elastic.easeOut} );

					}

				}



				break;

		}

	}



}



}

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×