Advertisement

Enhance Your Flash Layouts with Draggable Windows

by
Student iconAre you a student? Get a yearly Tuts+ subscription for $45 →

In this tutorial you'll learn how to create draggable windows using Flash and AS3. I'll cover the basics of drag&drop, window bounds, adding content, and how to minimize the window.


Final Result Preview

Let's take a look at the final result we will be working towards:


Step 1: Create a New File

Okey, let's gooo! Create a new document by hitting CTRL+N and selecting Flash File (ActionScript 3). Set the stage size to 600x400 px and the background color to #EEE. In the Properties window, set the class to windows and save your file as windows.fla.


Step 2: Design the windowArea

Select the Rectangle Tool (R) and draw a rectangle with 280x90 px. Select your shape, go to the Color palette (Window > Color) and create a gradient from #FFF to #CCC.

Hit F for the Gradient Tool, select your gradient, rotate it 90 degrees (by holding the Shift button while you rotate) and shorten it so it adapts the rectangle.

Select all the shape, hit F8 to Convert to Symbol, name it windowArea and set the registration point to the top left.

Select the symbol and in the Properties window set the instance name to windowArea.

For the border, use the Glow filter, with a 2px blur, strength 500%, color #666666. I used a glow because if you use a stroke, when you resize the Window the stroke will also resize.


Step 3: Design the windowBar Button

Select the Rectangle Tool (R) again and draw a rectangle with 280x22 px and a 1px stroke with the color #666. Create another rectangle on top of this, but this time in the Rectangle Options set the Rectangle corner radius to 5.

Now, eliminate the necessary corners like on the image below.

Then, paint your shape, select it, go to the Color palette (Window > Color) and create a gradient from #999 to #333. Rotate the gradient 90 degrees, like we did on the previous step.

Select the all shape, hit F8. Name: windowBar; Type: Button; Registration: top left.

Select the symbol and in the Properties window set the instance name to windowBar.

Double click the shape, create keyframes for the Over and Down states. Now change the colors for each one.

I've chosen:

  • Over: gradient from #FF9900 to #CC6633
  • Down: gradient from #9933CC to #660099

Step 4: Create the Minimize Button

Create a round rectangle with 14x11 px, 5px radius, and change it so it looks something like below.

The minus sign you do by creating a rectangle 5x2 px with the color #999. Set the instance name to minimizeBtn.

I used the same colors from the windowBar, but the UP State with a 40% alpha for the gradient.


Step 5: Create the Window

Arrange all shapes in form of a window, hit F8 and create a MovieClip with the name window and registration: top left.

In the Library, right click the Window and go to Properties. Set the class to window. This way the window will be assigned to the class we'll be creating later.

Select the symbol and in the Properties window set the instance name to window. In the Filters, click Add filter (the circled button in the image below), and add a Drop Shadow with the color #333 like below:

Double-click the symbol to edit it. Select all (CTRL+A), Right Click > Distribute to layers.

In a new layer, write the text for the window's title with Arial, 11pt, color #CCC, letter-spacing: 1. Set it to Dynamic Text and name it windowTitle.


Step 6: Create the ActionScript File

Now that the design is complete, let's start coding our scene. The first thing we'll do is create our ActionScript file.
Hit Ctrl+N or go to File > New and select ActionScript File. Save it in the same directory and with the same name (windows.as) of your FLA file.

Now let's create our package and import the necessary classes:

package {
	import flash.display.MovieClip;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.KeyboardEvent;
	import flash.events.ContextMenuEvent;
	import flash.geom.Rectangle;
	import flash.filters.DropShadowFilter;
	import flash.text.TextFormat;
	import fl.transitions.Tween;
	import fl.transitions.easing.*;
	import fl.transitions.TweenEvent;
	
	public class window extends MovieClip {
		
	}
}

Step 7: Add Event Listeners

Now you need to assign functions to our buttons. You'll need a function to when we start to drag the windowBar, another to stop the drag, one to bring the window to top when you click it, and another to minimize it.

Add these Event Listeners to the public function Window() in our code:

public class window extends MovieClip {
	
	// variables
	public var title:String;
	
	public function Window() {
	
		// set windowTitle
		title = windowTitle.text;
		windowTitle.mouseEnabled = false;
		
		// windows functions
		this.addEventListener(MouseEvent.MOUSE_UP, onWindowClick);
		this.windowBar.addEventListener(MouseEvent.MOUSE_DOWN, onWindowStartDrag);
		this.windowBar.addEventListener(MouseEvent.MOUSE_UP, onWindowStopDrag);
		this.minimizeBtn.addEventListener(MouseEvent.MOUSE_UP, minimizeWindow);
	}
	
}

The public var title is used for the window's title. We'll be using this later.

Since the windowTitle is a dynamic text we disable its mouse functions so that they won't affect the dragging area of the windowBar.


Step 8: onWindowStartDrag Function

This is where we start having fun! Copy the following code after the public function Window():

/* START DRAG
**********************************************************/
private function onWindowStartDrag(e:MouseEvent):void {

	var windowWidth  = this.width;
	var windowHeight = this.height;

	var windowBarWidth  = e.target.width;
	var windowBarHeight = e.target.height;

	var boundsRect:Rectangle;

	// window's draggable boundaries
	if (windowArea.visible) {
		boundsRect = new Rectangle(0, 0, stage.stageWidth-windowWidth, stage.stageHeight-windowHeight);
	} else {
		boundsRect = new Rectangle(0, 0, stage.stageWidth-windowBarWidth, stage.stageHeight-windowBarHeight);
	}
	//trace(boundsRect);
	this.startDrag(false, boundsRect);

	// bring window to front
	stage.addChild(this);
}

The first thing we do here is create variables to the widths and heights of the Window and the windowBar.

Next, the window's boundaries. We'll create two boundaries: one when the window is normal (if windowArea is visible) and another when it is minimized. You do this by creating a rectangle with the size of the stage. The rectangle supports four attributes (x, y, width, height). It'll start in the corner of the screen (x: 0; y: 0) and extend to the other corner of the screen. Because the bounds are related to the registration point of the window, we'll need to subtract the window width and height (or the windowBar's in case the window is minimized).

After the bounds have been set, we'll set the window to drag. We'll drag this, the Window class. In other words, the whole window.

this.startDrag(false, boundsRect);

The startDrag function supports two attributes: lockCenter and bounds. If you don't want any bounds just write this:

this.startDrag(false);

If we have several windows we'll need to bring the current window to the top of the display. We do this with the addChild by adding it again to stage:

// bring window to front
stage.addChild(this);

Step 9: onWindowStopDrag Function

This one is really simple. We'll use the stopDrag function here. Just copy the following to your code after the previous onWindowStartDrag function:

/* STOP DRAG
**********************************************************/
private function onWindowStopDrag(e:MouseEvent):void {
	this.stopDrag();
}

Step 10: Bring Window to Front

Again, really simple. When we click the window we'll bring it to front using addChild.

/* WINDOW CLICK
**********************************************************/
private function onWindowClick(e:MouseEvent):void {
	// bring window to front
	stage.addChild(this);
}

Step 11: minimizeWindow Function

To minimize/show the window, we'll toggle the visibility of the windowArea like this:

/* MINIMIZE WINDOW
**********************************************************/
private function minimizeWindow(e:MouseEvent):void {
	
	windowArea.visible = !windowArea.visible;
}

You can improve this by fading out the window and hiding it, and vice-versa:

/* MINIMIZE WINDOW
**********************************************************/
private function minimizeWindow(e:MouseEvent):void {
	
	var fade:Tween;
	
	if (windowArea.visible) {
		fade = new Tween(windowArea, "alpha", Strong.easeOut, 1, 0, 0.5, true);
		fade.addEventListener(TweenEvent.MOTION_FINISH, fadeFinish);
	} else {
		fade = new Tween(windowArea, "alpha", Strong.easeOut, 0, 1, 0.5, true);
		windowArea.visible = !windowArea.visible;
	}
	
	fade.start();
	
	function fadeFinish(e:TweenEvent):void {
		windowArea.visible = !windowArea.visible;
	}
}

The Tween supports the following values:

Tween(object, "property", EasingType, begin, end, duration, useSeconds);

For more extensive reading, use the LiveDocs.

In our case, what we're doing is, if the windowArea is visible (meaning: not minimized), it will fade out the windowArea and when the tween finishes (TweenEvent.MOTION_FINISH), it will hide the windowArea. Vice versa if it's minimized.


Step 12: Set the Title

We'll use the variable t to change the windowTitle. The other two lines are just to resolve a letter spacing issue. If you don't write them Flash will reset the letter spacing to zero.

/* SET WINDOW'S TITLE
**********************************************************/
public function Title(t:String):void {
	
	var fmt:TextFormat = windowTitle.getTextFormat();
	windowTitle.text = t;
	windowTitle.setTextFormat(fmt); // letter spacing issue
	
	title = t;
}

This function will be used later like this:

YourWindowName.Title("Name of your window");

Step 13: Set the Size

This function will receive two attributes: the Width and Height of the window. If neither is filled, it will be set to the default size (280x112 px)

What we do here is change the width of the windowBar, the windowArea and the windowTitle. For the height we just change the windowArea's, leaving the height of the Window to its default size, just like a normal window.

When resizing we'll have to reset the position of the Minimize Button. Which is equal to the window's width minus the button's width and 6px.

/* SET WINDOW'S SIZE
**********************************************************/
public function Size(Width:int = 280, Height:int = 112):void {
	
	// change width
	windowBar.width = Width;
	windowArea.width = Width;
	windowTitle.width = Width - 45;
	
	// change content height
	windowArea.height = Height;
	
	// reset minimizeBtn scale/position
	minimizeBtn.x = Width - minimizeBtn.width - 6;
}

This function will be used later like this:

YourWindowName.Size(350,200);

Step 14: Give it a Nice Shadow

Remember when we placed a Drop Shadow under the Window? Well, if you place the window by code you'll need to add the drop shadow by code as well.

All of the above attributes can be set by code. Copy the function and change the values according to your own taste:

/* SET FILTER: DROP SHADOW
**********************************************************/
public function DropShadow(color:String = "333333"):void {
	
	var dropShadow:DropShadowFilter = new DropShadowFilter();
	
	dropShadow.blurX = 5;
	dropShadow.blurY = 5;
	dropShadow.strength = 1;
	dropShadow.quality = 1; // 1- low; 2- medium; 3- high (max: 15)
	dropShadow.angle = 45;
	dropShadow.distance = 1;
	dropShadow.alpha = 1;
	dropShadow.knockout = false;
	dropShadow.inner = false;
	dropShadow.hideObject = false;
	dropShadow.color = int("0x" + color);
	
	this.filters = new Array(dropShadow); // add filter to the window
}

This function will receive a String with the color's hexadecimal code. If this is not filled, the default color value will be #333333.

The quality can go from 1 to 15, being 1 2 3 - low, medium and high. We used low, here.

The color must be converted from a String to an int.

After defining the attributes we must add the filter to the window like in the last line. This will create an Array of filters. Which means you could add other filters to the Window as well.

this.filters = new Array(dropShadow);

This function will be used later like this:

YourWindowName.DropShadow("FF0000"); // adds a red shadow

Step 15: Adding a Window by Code

Now change to your Flash file, create a new layer, name it as3 and hit F9 for the ActionScript (or go to Window > Actions).

Adding a Window is very simple. All you need to do is create a variable (let's call it myWindow), assigning it to the Window class and the add the Window to stage:

var myWindow:window = new window;

addChild(myWindow);

This will produce a Window with its default values.


Step 16: Changing the Values

You can change several attributes of the Window:

  • Title
  • Shadow
  • Size
  • X and Y position
  • Content

Again, the first thing to do is to create the variable assigned by the Window class:

var myWindow:window = new window;

Then you can start changing the attributes:

Changing the Title:

myWindow.Title("Cabo Verde");

Changing the Shadow:

myWindow.DropShadow("66CC00"); // adds a nice lime shadow

Changing the Size:

myWindow.Size(350,200);

Changing the Position:

myWindow.x = 20;
myWindow.y = 20;

Adding the window to stage:

addChild(myWindow);

The all code will be like this:

var myWindow:window = new window;

myWindow.Title("Cabo Verde");
myWindow.DropShadow("66CC00");
myWindow.Size(350,200);
myWindow.x = 20;
myWindow.y = 20;

addChild(myWindow);

Step 17: Using Additional Windows

Here's another example with two windows added by code and a default one in the stage:

var janela:window = new window;
var janela02:window = new window;

janela.Title("Cabo Verde");
janela.DropShadow("66CC00");
janela.Size(350,200);
janela.x = 20;
janela.y = 20;

janela02.Title("Ninjas!");
janela02.DropShadow("FF0000");
janela02.Size(250,200);
janela02.x = 40;
janela02.y = 150;

addChild(janela);
addChild(janela02);

If you need to know the window's title, you can use this:

trace(janela.title);

Milestone

Well done for following so far! You should now have achieved a result similar to what we looked at in the beginning:


Step 18: Different Content in the Windows

If you notice by now, you can change all the window's attributes but the content remains the same. So let's create the content.

Open the Window's MovieClip, create a new layer for the content and go to Insert > New Symbol (CTRL+F8). Choose MovieClip, name it content and hit OK. Now place it at X:0, Y:22.

Select the new content symbol you just created, and set its instance name to CONTENT.

Double-click the content, name the existing layer content and create another one named as3. In the latter, hit F9 and write:

stop();

This will be our default content. Meaning, nothing!

Now create another keyframe and place an image for example. Bear in mind the size of the window you'll be using. Add another keyframe and write some text in it. Now we have 3 keyframes: 1. no content, 2. image, 3. text.

As for the code, add this to your class file:

/* CHANGE CONTENT
**********************************************************/
public function Content(c:int):void {
	
	CONTENT.gotoAndStop(c);
}

Really simple. We'll just say which keyframe we'll want to go to.

You'll also need to change the minimizeWindow function to this:

/* MINIMIZE WINDOW
**********************************************************/
private function minimizeWindow(e:MouseEvent):void {
	
	var fade:Tween;
	
	if (windowArea.visible) {
		CONTENT.visible = !CONTENT.visible;
		fade = new Tween(windowArea, "alpha", Strong.easeOut, 1, 0, 0.5, true);
		fade.addEventListener(TweenEvent.MOTION_FINISH, fadeFinish);
	} else {
		fade = new Tween(windowArea, "alpha", Strong.easeOut, 0, 1, 0.5, true);
		windowArea.visible = !windowArea.visible;
		CONTENT.visible = !CONTENT.visible;
	}
	
	fade.start();
	
	function fadeFinish(e:TweenEvent):void {
		windowArea.visible = !windowArea.visible;
	}
}

Step 19: Changing the Content in the Code

In the previous example, add this to the code:

janela.Content(2); // goes to the image keyframe

Here is the complete code:

var janela:window = new window;
var janela02:window = new window;

janela.Title("Cabo Verde");
janela.DropShadow("66CC00");
janela.Size(350,240);
janela.Content(2); // goes to the image keyframe
janela.x = 20;
janela.y = 20;

janela02.Title("Ninjas!");
janela02.DropShadow("FF0000");
janela02.Size(250,200);
janela02.Content(3); // goes to the text keyframe
janela02.x = 40;
janela02.y = 150;

addChild(janela);
addChild(janela02);

Conclusion

So, there's a simple way to create a draggable window (much like we see on Windows). If you want to go further, you can change the content MovieClip, adding text, buttons, images, etc. You could add scrollbars, call content through XML, or whatever you can think of. The possibilities are endless!

Here's another awesome example:

This is eXOTRik, and I hope you found this useful. It's my first tutorial, hope to bring you some more ninja tricks. Ayaaaa!

Advertisement