Posts Tagged ‘deconstruction’

Deconstruct red-issue.com

Sunday, March 22nd, 2009

In one of my Flash courses taught at Humber College we often choose web sites to deconstruct. Today we have chosen red-issue.com.

First let’s figure out what we want to learn from this web site. We are going to create a grid of images where each image will occupy the full screen. This grid will be navigated by drawing arrows.

First lets import all the Flash and custom classes we will need:

import flash.display.StageScaleMode;
import flash.display.StageAlign;
import flash.events.Event;
import fl.transitions.Tween;
import fl.transitions.easing.*;
import fl.transitions.TweenEvent;
import com.foxaweb.ui.gesture.*;

The last import statement is a class that helps us recognize mouse gestures. The Mouse Gestures Class was written by Didier Brun.

Next we need a few variables to define the grid dimensions and to keep track of what row and column we are currently looking at.

var verticalCounter:Number = new Number();
var horizontalCounter:Number = new Number();
var gridWidth:Number=new Number(4);
var gridHeight:Number=new Number(3);

On the Enter Frame Event we will check the values in the horizontalCounter and verticalCounter variable and position the grid accordingly. That way when someone draws a down arrow we will simply add one to the verticalCounter variable.

stage.addEventListener(Event.ENTER_FRAME,enterFrameHandler);
function enterFrameHandler(evt:Event):void {
     var targetX:Number = new Number(stage.stageWidth * horizontalCounter);
     grid_mc.x += (targetX - grid_mc.x) / 3;
     var targetY:Number = new Number(stage.stageHeight * verticalCounter);
     grid_mc.y += (targetY - grid_mc.y) / 3;
}

Wen using the Mouse Gestures Class we need to tell the Class what gestures to look for. These gestures are determined by a set of numbers. For example a up arrow starting from the left consists of a 7 motion and then a 1 motion. Here are the motions tracked and the numbers for each.

Here is the code to create a new Mouse Gesture and add the four different directions as well as the zoom in and zoom out gestures.

var mg:MouseGesture = new MouseGesture(stage);
mg.addGesture("UP","71");
mg.addGesture("UP","53");
mg.addGesture("DOWN","17");
mg.addGesture("DOWN","35");
mg.addGesture("LEFT","13");
mg.addGesture("LEFT","75");
mg.addGesture("RIGHT","31");
mg.addGesture("RIGHT","57");
mg.addGesture("OUT","0");
mg.addGesture("OUT","4");
mg.addGesture("IN","4321076542");

Now with this class we are going to listen for a few specific events.

mg.addEventListener(GestureEvent.GESTURE_MATCH,matchHandler);
mg.addEventListener(GestureEvent.NO_MATCH,noMatchHandler);
mg.addEventListener(GestureEvent.START_CAPTURE,startHandler);
mg.addEventListener(GestureEvent.STOP_CAPTURE,stopHandler);

A Mouse Gesture is defined by the user pressing their mouse down, moving the mouse and then releasing. When a Mouse Gesture matches one of the items defines in our list the matchHandler function is executed. This function makes the necessary changes to verticalCounter or horizontalCounter and then removes the drawing.

function matchHandler(evt:GestureEvent):void{
     switch (evt.datas){
          case "UP":
               if(verticalCounter < 0){
                    verticalCounter++;
               }
          break;
          case "DOWN":
               if(verticalCounter > 1 - gridHeight){
                    verticalCounter--;
               }
          break;
          case "LEFT":
               if(horizontalCounter > 1 - gridWidth){
                    horizontalCounter--;
          }
          break;
          case "RIGHT":
               if(horizontalCounter < 0){
                    horizontalCounter++;
               }
          break;
          case "IN":
               // Zoom in code would go here
          break;
          case "OUT":
               // Zoom out code would go here
          break;
     }
     var tweenOut:Tween = new Tween(draw_mc,"alpha",Strong.easeOut,1,0,6);
}

This code was taken from the GesturesDemo.as file that comes with the Mouse Gestures Class. When the Start Capture Event is triggered this code draws whatever the user does.

function startHandler(e:GestureEvent):void{
     draw_mc.graphics.clear();
     draw_mc.alpha = 1;
     draw_mc.graphics.lineStyle(4,0x444444);
     draw_mc.graphics.moveTo(mouseX,mouseY);
     addEventListener(Event.ENTER_FRAME,capturingHandler);
}

When the user lets go of their mouse the Stop Capture Event is triggered and executes the startHandler function. This function stops the drawing initialized by the startHandler function.

function stopHandler(e:GestureEvent):void{
     removeEventListener(Event.ENTER_FRAME,capturingHandler);
}

This function actually performs the drawing. It is started by the startHandler function and is stopped by the stopHandler function.

function capturingHandler(e:Event):void{
     draw_mc.graphics.lineTo(mouseX,mouseY);
}

When the user releases the mouse button if there is no match the noMatchHandler function removes the drawing.

function noMatchHandler(e:GestureEvent):void{
     var tweenOut:Tween = new Tween(draw_mc,"alpha",Strong.easeOut,1,0,6);
}

The next set of code creates the photo grid and makes any necessary changes when the Stage is re-sized. You can get a much more in depth description of this code from the Photo Grid post.

stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;

This list of images could eventually come from an XML document but for now we will just use an array.

var imageDir:String = new String( "http://adambenjamin.com/blog/wp-content/" );
var gridArray:Array=new Array(
     ({image:"img_0001.jpg",imageWidth:800,imageHeight:532}),
     ({image:"img_0002.jpg",imageWidth:800,imageHeight:532}),
     ({image:"img_0003.jpg",imageWidth:800,imageHeight:532}),
     ({image:"img_0004.jpg",imageWidth:800,imageHeight:532}),
     ({image:"img_0005.jpg",imageWidth:800,imageHeight:532}),
     ({image:"img_0006.jpg",imageWidth:800,imageHeight:532}),
     ({image:"img_0007.jpg",imageWidth:800,imageHeight:532}),
     ({image:"img_0008.jpg",imageWidth:800,imageHeight:532}),
     ({image:"img_0009.jpg",imageWidth:800,imageHeight:532}),
     ({image:"img_0010.jpg",imageWidth:800,imageHeight:532}),
     ({image:"img_0011.jpg",imageWidth:800,imageHeight:532}),
     ({image:"img_0012.jpg",imageWidth:800,imageHeight:532}));

var movieArray:Array = new Array();
var maskArray:Array = new Array();
var loaderArray:Array = new Array();

stage.addEventListener(Event.RESIZE, resizeHandler);
function resizeHandler(evt:Event):void {
     for (var i:int = 0; i < gridArray.length; i ++) {
          resizeMask(i);
          resizeImage(i);
          reposition(i);
     }
}

for (var i:int = 0; i < gridArray.length; i ++) {
     maskArray[i] = new MovieClip();
     maskArray[i].graphics.lineStyle(0,0x000088);
     maskArray[i].graphics.beginFill(0x000088);
     maskArray[i].graphics.drawRect(0,0,1,1);
     maskArray[i].graphics.endFill();
     resizeMask(i);
     grid_mc.addChild(maskArray[i]);
     movieArray[i] = new MovieClip();
     var request:URLRequest=new URLRequest(imageDir + gridArray[i]["image"]);
     loaderArray[i] = new Loader();

     loaderArray[i].load(request);
     resizeImage(i);
     movieArray[i].addChild(loaderArray[i]);
     grid_mc.addChild(movieArray[i]);
     movieArray[i].mask=maskArray[i];
     reposition(i);
}

function reposition(i:int):void{
     maskArray[i].x = i % gridWidth * Number(stage.stageWidth);
     maskArray[i].y = Math.floor( i / gridWidth ) * Number(stage.stageHeight);
     movieArray[i].x = i % gridWidth * Number(stage.stageWidth);
     movieArray[i].y = Math.floor( i / gridWidth ) * Number(stage.stageHeight);
}

function resizeMask(i:int):void{
     maskArray[i].width = Number(stage.stageWidth);
     maskArray[i].height = Number(stage.stageHeight);
}

function resizeImage(i:int):void {
     var widthRatio:Number = Number(stage.stageWidth)/gridArray[i]["imageWidth"];
     var heightRatio:Number = Number(stage.stageHeight)/gridArray[i]["imageHeight"];
     if( widthRatio > heightRatio){
          movieArray[i].scaleX = widthRatio;
          movieArray[i].scaleY = widthRatio;
     }else{
          movieArray[i].scaleX = heightRatio;
          movieArray[i].scaleY = heightRatio;
     }
}

The Flash plugin is required to view this object.

Download Red Issue FLA

Deconstruct neave.com part 2

Saturday, February 21st, 2009

This post is the completion of deconstructing the web site neave.com. Part one of this deconstructing can be found here.

Now that we have individually built all the components we just need to put them all together into a web site. On your main timeline create the following layer and frame structure:

On the footer timeline create your footer Movie Clip and give it the name footer_mc. On the main layer put your content Movie Clip and name it content_mc. Inside yout content Movie Clip create the following layer and frame structure:

Download the Flash file without the Actionscript

On frame one of our actions layer on the stage enter the following Actionscript:

import flash.display.StageScaleMode;
import flash.display.StageAlign;
import flash.events.Event;

stage.scaleMode=StageScaleMode.NO_SCALE;
stage.align=StageAlign.TOP_LEFT;
stage.addEventListener(Event.RESIZE, resizeHandler);

resizeHandler(null);

function resizeHandler(event:Event):void {
     var sw:Number=stage.stageWidth;
     var sh:Number=stage.stageHeight;
     footer_mc.y = sh - 50;
     footer_mc.x = ( sw - 600 ) / 2;
     content_mc.y = ( sh - 200 ) / 2;
     content_mc.x = ( sw - 600 ) / 2;
}

This code imports a few required classesand re-positions our site content based on the size of the Flash viewable area. This code is executed once at the begining and again when ever the stage is resized. This code, and most of teh code on this page, is discussed in more detail in the Deconstructing neave.com Part 1 post. Most of this code was origianly taken from a Creating Liquid GUIs article from the Adobe site.

Next click into the content_mc Movie Clip and on frame one of the actions layer goes the rest of our code. Lets start with importing a few required classes:

import gs.TweenMax;
import gs.easing.*;
import flash.display.Bitmap;
import flash.display.BitmapData;

The first two import commands are importing non Flash classes. You will need to have the TweenMax class in the same folder as your fla. I’ll mention this one more time….most of this code is broken down in more detail in the initial Deconstructing neave.com post.

Next we are going to create a Movie Clip that will play a 320 pixel by 100 pixel FLV file when a menu option triggers a roll over event. The videos we will be using are lines, colours, marsh and waves.

var firstVideo:MovieClip = new MovieClip();
video_mc.addChild(firstVideo);

Lets also set up everything we need to play a video so that all the rollover code will have to do is select the video to play.

var nc:NetConnection = new NetConnection();
nc.connect(null);
var ns:NetStream = new NetStream(nc);
ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR,asyncErrorHandler);
function asyncErrorHandler(evt:AsyncErrorEvent):void {
     // Ignore errors
}
var vid:Video = new Video(320,100);
vid.attachNetStream(ns);
firstVideo.addChild(vid);

The video we play on roll over will need to fill whatever space is available. Lets fill 800 pixels of space using videos that are 320 pixels wide. These two value will be used to determine how may times to repeat the video. There is more information on this concept on the Videos Indefinately post.

var widthToFill:Number = new Number(800);
var videoWidth:Number = new Number(320);

We will also need an unknown number of Movie Clips, Bitmap Objects and Bitmap Data Objects; so each time we create another set of these items we are going to store them in three Arrays.

var videoArray:Array = new Array();
var bitmapArray:Array = new Array();
var bitmapDataArray:Array = new Array();

Now we’re all set….lets create enough Movie Clips and Bimap Objects to fill the space specificed above.

for( var i:int = 1; i < widthToFill / videoWidth; i ++ ) {
     videoArray[i] = new MovieClip();
     videoArray[i].x = i * 320;
     bitmapDataArray[i] = new BitmapData(320,100,false,0x000000);
     bitmapArray[i] = new Bitmap(bitmapDataArray[i]);
     if( i % 2 == 1 ){
          bitmapArray[i].scaleX = -1;
          bitmapArray[i].x = 320;
     }
     videoArray[i].addChild(bitmapArray[i]);
     video_mc.addChild(videoArray[i]);
}

The first line determins how many sets we are going to need and loops the excerpt of code accordingly, The next two commands create a new Movie Clip and positions it. The two after that create a new Bitmap Object and a Bitmap Data Object. The code in the if statement will flip and reposition every second Movie Clip so are videos look seamless. And finally we add our Bitmap Object to our Movie Clip and we add our Movie Clip to our container Movie Clip.

Now we just need to set up a function to update our Bitmap Data Objects on the Enter Frame Event.

function enterFrameHandler(evt:Event):void {
     for( var i:int = 1; i < widthToFill / videoWidth; i ++ ) {
          bitmapDataArray[i].draw(firstVideo);
     }
}

Finally! Our video roll overs are all set to go. Lets move on to adding the roll over code to each of our butons. First we need to give out container Movie Clip a staring blur and zero alpha.

TweenMax.to( video_mc, 0.1, {blurFilter:{blurX:20, blurY:20}, autoAlpha:0} );

This next excerpt is our actual roll over code. When our visitor rolls over our first option a number of things are happening. First we tween the vertial_mc, horizontal_mc and stripes_mc to the desired colours. Next we change the text to inform our visitor what sectino they have just rolloed over, in this example we choose “Neave Games”. Next we tween our mask)mc and stripes_mc to make sure the whole text is visible. In this case 395 is sufficient. There would be some more complex methods of figuring out this number, but for now we just guessed a few times until it looked right. And finally we play the desired video, activate our Enter Frame Functiuon from above and unblur and make visible the video.

option1_mc.buttonMode=true;
option1_mc.addEventListener( MouseEvent.ROLL_OVER, option1OverHandler );
function option1OverHandler( evt:MouseEvent ):void {
     TweenMax.to(vertical_mc, 3, {tint:0x631553});
     TweenMax.to(horizontal_mc, 3, {tint:0xff00cc});
     TweenMax.to(stripes_mc, 3, {tint:0xff00cc});
     title_tb.text = "Neave Games";
     TweenMax.to(mask_mc, 0.5, {x:395});
     TweenMax.to(stripes_mc, 0.5, {x:395});
     ns.play("flash_neave_lines.f4v");
     video_mc.addEventListener(Event.ENTER_FRAME,enterFrameHandler);
     TweenMax.to( video_mc, 1, {blurFilter:{blurX:0, blurY:0}, autoAlpha:1} );
}

This next code is pretty much identical to the above roll over code with a diffent video to play, different colours and a different x position.

option2_mc.buttonMode=true;
option2_mc.addEventListener( MouseEvent.ROLL_OVER, option2OverHandler );
function option2OverHandler( evt:MouseEvent ):void {
     TweenMax.to(vertical_mc, 3, {tint:0x185e1d});
     TweenMax.to(horizontal_mc, 3, {tint:0x1ff82e});
     TweenMax.to(stripes_mc, 3, {tint:0x1ff82e});
     title_tb.text = "Neave Television";
     TweenMax.to(mask_mc, 0.5, {x:475});
     TweenMax.to(stripes_mc, 0.5, {x:475});
     ns.play("flash_neave_marsh.f4v");
     video_mc.addEventListener(Event.ENTER_FRAME,enterFrameHandler);
     TweenMax.to( video_mc, 1, {blurFilter:{blurX:0, blurY:0}, autoAlpha:1} );
}

These last two sets of code can be duplicated for each option you want to have in your menu. On the other hand, on roll out we can reuse the same function for eavery button.

option1_mc.addEventListener( MouseEvent.ROLL_OUT, optionOutHandler );
option2_mc.addEventListener( MouseEvent.ROLL_OUT, optionOutHandler );
option3_mc.addEventListener( MouseEvent.ROLL_OUT, optionOutHandler );
option4_mc.addEventListener( MouseEvent.ROLL_OUT, optionOutHandler );
function optionOutHandler( evt:MouseEvent ):void {
     TweenMax.to(vertical_mc, 3, {tint:0x111111});
     TweenMax.to(horizontal_mc, 3, {tint:0x222222});
     TweenMax.to(stripes_mc, 3, {tint:0x222222});
     title_tb.text = "Neave.com";
     TweenMax.to(mask_mc, 0.5, {x:325});
     TweenMax.to(stripes_mc, 0.5, {x:325});
     ns.pause();
     video_mc.removeEventListener(Event.ENTER_FRAME,enterFrameHandler);
     TweenMax.to( video_mc, 1, {blurFilter:{blurX:20, blurY:20}, autoAlpha:0} );
}

And there we have it…something that resembles neave.com. Maybe not quite as nice but not bad for two three hour classes.

The Flash plugin is required to view this object.

Download the Complete Flash File

Deconstruct pepsi.com

Sunday, February 8th, 2009

During a preloader class we decided we wanted to re-create the initial preloader at pepsi.com. At first glance it looks a little chaotic.

Some of the stuff happening during this preloader was a little too much so we decided that we were going to create a preloader which did the following:

  1. Display the percentage loaded in a random location within the stage
  2. Tween each number to the center of the stage
  3. Tween each number to have a with and height of zero

So just like the previous preloader post create a timeline like the following:

Put a stop(); action on frame one and five of the actions layer and and for now put something like a fairy large on frame five of the content layer. This will give us something to actually preload.Now go back to frame one on the action layer and open up your actions panel. This is where the rest of our Actionscript is going to go.

For this example we’re just going to use the built in Flash Tween class so right before your stop(); action add the following code:

import fl.transitions.Tween;
import fl.transitions.easing.*;

Next we need to define a TextFormat to use with our percentage numbers. So right after your stop(); action add the following TextFormat:

var newFormat:TextFormat = new TextFormat();
newFormat.size = 80;
newFormat.font = "Arial";
newFormat.color = 0x666666;

This tells our percentage numbers to be Arial, 80px and a grey. There are lots more formatting options you can check out at the TextFormat page in the Actionscript Language Reference.

For each percentage number we place on the stage we are going to need four tweens. By the end of our loading animation we likely will have used around 400 tweens. To prevent any conflicts by using the same teen names over and over we are going to place all of our tweens in four arrays:

var tweenX:Array = new Array();
var tweenY:Array = new Array();
var tweenScaleX:Array = new Array();
var tweenScaleY:Array = new Array();

We will also use a counter to track which set of tweens we are currently on:

var tweenCounter:Number = new Number(0);

Next we need to create a function that is executed whenever the download made progress. This function contains the bulk of the code:

this.loaderInfo.addEventListener(ProgressEvent.PROGRESS,onLoaderProgress);
function onLoaderProgress(evt:ProgressEvent):void {
     var percent:Number=evt.bytesLoaded/evt.bytesTotal;
     var newNumber:TextField = new TextField();
     newNumber.text = String( Math.round( percent * 100 ) );
     newNumber.selectable = false;
     newNumber.x = stage.stageWidth * Math.random() - newNumber.width / 2;
     newNumber.y = stage.stageHeight * Math.random() - newNumber.height / 2;
     newNumber.setTextFormat( newFormat );
     addChild( newNumber );

The first half of this function creates a new TextField object with the current percent loaded and places it on a random location on the stage. I also applies the TextFormat defined earlier.

The second half of the function tweens the new TextField to the center of the stage and to a width and height of zero. Each of these tweens are place in an array kept track with the tweenCounter variable.

     tweenX[tweenCounter] = new Tween(newNumber,"x",Strong.easeOut,newNumber.x,stage.stageWidth / 2,24);
     tweenY[tweenCounter] = new Tween(newNumber,"y",Strong.easeOut,newNumber.y,stage.stageHeight / 2,24);
     tweenScaleX[tweenCounter] = new Tween(newNumber,"scaleX",Strong.easeOut,1,0,24);
     tweenScaleY[tweenCounter] = new Tween(newNumber, "scaleY",Strong.easeOut,1,0,24);
     tweenCounter ++;
}

Finally we need a function to run when the downloading is complete. This function will simply run a play(); action to play out the rest of the swf.

this.loaderInfo.addEventListener(Event.COMPLETE,onLoaderComplete);
function onLoaderComplete(evt:Event):void {
     play();
}

And that’s it! We have a time warp looking Pepsi preloader!! Click the Pepsi image to replay the preloader:

The Flash plugin is required to view this object.

Download the Pepsi Preloader

Deconstruct neave.com

Friday, February 6th, 2009

A large part of a few of the Flash classes I teach at Humber College is to take a web site, chosen by students, and recreate it form scratch. Today we have chosen neave.com.

Neave.com is the personal page of Paul Neave. He has some pretty advanced Flash files wich make for some great viewing and he even makes his source files available for downloading!!

At first glance this site may look pretty complicated. But it’s actually not; it’s just a whole lot of fairly simple concepts bundled together to create a great looking navigation. We will not be recreating everything from this site. First of all we’re only going to deconstruct the home page and we are going to focus on the navigation. Here are the concepts we want to take away from this conversion:

  1. Building a full browser web site that properly adjusts to the browser size
  2. Using a Tween class to tween the colour, x coordinate and width of movie clips
  3. Mirroring a video

Concept 1: Full Browser Web Sites

Lets start off with simply making a three section Flash file to represent a header, body and footer. We will use Actionscript to force these three sections to fill the entire space available.

I know what you’re thinking…it kind of represents the Azerbaijan flag…right…!?

Start by creating three separate rectangles and convert them into three separate movie clips. Give them the instance names header_mc, body_mc and footer_mc.

Next we need to import some classes that are not loaded by default:

import flash.display.StageScaleMode;
import flash.display.StageAlign;
import flash.events.Event;

Now lets set some properties so our Flash file scales properly.

stage.scaleMode=StageScaleMode.NO_SCALE;
stage.align=StageAlign.TOP_LEFT;

The first line will ensure that the content of our Flash file is always displayed at 100% and the second line set the top left corner as the anchor point.

Next we add an event to our stage that will execute whenever the stage is re-sized. The event we need to use is the RESIZE event.

stage.addEventListener(Event.RESIZE, resizeHandler);

This line will call the resizeHandler function, which we will create next, whenever the stage is re-sized.

function resizeHandler(event:Event):void {
     header_mc.width=body_mc.width=footer_mc.width=stage.stageWidth;
     body_mc.y=header_mc.height;
     body_mc.height=stage.stageHeight-header_mc.height-footer_mc.height;
     footer_mc.y=stage.stageHeight-footer_mc.height;
}
resizeHandler(null);

Our resizeHandler function will set the width of the header_mc, body_mc and footer_mc to be equal to that of the stage. It will ensure that the body_mc fills the space between the header_mc and the footer_mc. And finally it will keep the header_mc at the very top and the footer_mc at the very bottom. And right at the end of that previous piece of code with execute the function to make sure the three movie clips start in the right positions.

The Flash plugin is required to view this object.

Download Full Screen FLA

A lot of this code was borrowed from James O’Reilly’s article called Creating liquid GUIs with Flash and ActionScript 3.0.

Concept 2: Tweening

The built in Flash Tween class is a great class for basic tweening but there are some very bright people out there who have written way better and much more versatile tweening classes. The site we are deconstructing requires that we tween a movie clip from one colour to another. This is one property that the Flash Tween class is not capable of completing so we are going to use Jack Doyle’s TweenLite class. His web site also has a few great tools to help you generate the Actionscript you need.

Once you have downloaded the TweenLite class you should have a gs folder in the same folder as your fla and swf. Now we need to import the TweenLite class for use in our fla.

import gs.TweenLite;
import gs.easing.*;

To tween a colour we simply run the TweenLite.to command and specify what movie clip we are tweening, what property we are tweening and what the new value of that property is. For example this line will tweena movie clip with the instance name rectangle_mc to a bright red.

TweenLite.to(rectangle_mc, 1, {0xff0000});

In the example file there is a form to choose what colour to tween to and a button to trigger that tween. I won’t explain that code here.

The Flash plugin is required to view this object.

Download Colour Tween FLA

Concept 3: Mirroring a Video

To achieve the effect on neave.com we will so need to use the Bitmap and Bitmap Data objects to mirror a video. There is a post on the Bitmap Object and there is a post on using Indefinate Videos.

Check out the post Deconstruct neave.com part 2 for the rest of this deconstruction.