The Matrix3D class

The Matrix3D class

The new Flash 10 classes now allow to create effects, which could only be created using frame to frame animation in the past. In the following I show an example of a slideshow where the slides are transitioned using the Matrix3D class. The first script is simply a slideshow script creating buttons. The xample was created with Flash CS4 but can be compiled with the Flex SDK. Previously I had posted a similar example in the pre CS4 phase. However, certain syntax has changed and so I made this example newly. You will also need some scripts from my AS3 script library or you can alter the script at that point by yourself.

Structure of the movie

The movie is structured into several classes:

The advantage of doing this is to have oversight over the movie scripts. To add a transition just add another subclass and initiate it in the document class. If you want to change a certain transition you need to make those changes only in the corresponding subclass.

In the following I am not showing the XML file and not going in detail through the slideshow script, but you can find the XML and the XMLSlideshow.as class. All files are also in the zip file, which is for download. The only part in the slideshow script, which we need to look at closer is the function to initiate changing the slides, which I will present here. This function is triggered when the thumbs are pressed. The individual steps are

         
private function mouseHandler (ev:MouseEvent):void
		{
		/*
We need to disable the thumbs here, since pressing a thumb while a transition is taking
place would cause serious problems. Mouse response is activated again, once the transition
is complete.
*/
			for (var i = 0; i < myXML.sub.length(); i++)
			{
				MovieClip(getChildByName("_mc" + i)).mouseEnabled = false;
			}
			imName.text = ev.currentTarget.slideName;
			myURL = ev.currentTarget.slideURL;
		/*
we create an array to randomly have different slide transitions. We have 3 different transitions. 
The other function parameters are "imageHolder", a MovieClip, which holds the images. 
Then there is the speed for transitioning (10) and the image url (myURL) and the name of the XML object
(myXML).
*/
			var rArray:Array = new Array("x","y","z");
			var ranNum:int = Math.random() * 4;
			_rotation = new RotationEffect  ;
			_rotation.slideTransition (imageHolder,10,myURL,myXML);
		/*
We load different classes for all the effects.
*/
			switch (rArray[ranNum])
			{
				case "x" :
					_x = new Xrotation  ;
					_x.timerHandler ();
					break;
				case "y" :
					_y = new Yrotation  ;
					_y.timerHandler ();
					break;
				case "z" :
					_z = new Zrotation  ;
					_z.timerHandler ();
					break;
				default :
					_rotation.timerHandler ();
			}
		}
		

Press to open the script for the abstract class RotationEffect. An abstract class is a superclass providing functions. This gives the advantage that code does not have to be rewritten in other classes. In this abstract class all the objects, which are required for the slideshow transition are defined as function parameters from the document class. Further, we declare a default slide transition function, which is a simple fadein-out function. All the subclasses for RotationEffect get their variables from this class.

Next we have one of the subclasses, which triggers a transitioneffect. The class extends the RotationEffect class and inherits all the parameters, which are required. Those variables have been defined as Getters in the abstract class and do not need to be defined newly.


package flashscript.CS4slideshow
{
	import flash.events.*;
	import flash.geom.*;
	import flash.display.MovieClip;
	import biz.Flashscript.utils.LoaderClassStatic;
	import flashscript.CS4slideshow.RotationEffect;
		/*
We are extending this class to a kind of abstract class, which holds many variables and a 
function to transition slides.
*/
	public class Yrotation extends RotationEffect
	{
		private var lcs:LoaderClassStatic = new LoaderClassStatic  ;
		/*
Only new variables need to be declared. Other variables are derived from the superclass
and declared there in form of getter statements.
*/
		private static var count:int;
		private static var rValue:Number;
		private static var _changed:Boolean;
		public function Yrotation ():void
		{
			super ();
		}
		/*
We override the timerhandler function in the superclass
*/
		override public function timerHandler ():void
		{
			_changed = true;
			count = 0;
			addEventListener (Event.ENTER_FRAME,newTransition);
		}
		/*
This is the actual function, where the transition is scripted.
*/
		private function newTransition (e:Event):void
		{
		/*
In this first part, we reduce the alpha value of the image holder, which once
the image has changed will come back.
*/
			if (_changed)
			{
				imageHolder.alpha -=0.1;
				if (imageHolder.alpha<=0)
				{
					imageHolder.alpha=0;
				}
			}
			else
			{
				imageHolder.alpha+=0.1;
			}
			if (imageHolder.alpha>=1)
			{
				imageHolder.alpha=1;

			}
		

This part of the class is the core, where the actual transition is triggered. We use the transform property of the Displayobject. One of the transform objects' properties is the matrix. We first specify the degrees steps for the rotation. We use a variable speed to have a bit more freedom in changing the speed. The final value should be a value, which gives a round number when divided by 360. We have the option here to have a positive or negative value. We then specify the coordinates for the axis, where the rotation occurs by using the Matrix3D.appendTranslation method. We actually don't need it, since we are not changing the position, but I added this line here for demonstration purposes. Then we code the actual rotation by using the Matrix3D.appendRotation method with the parameters "radius" and the "axis" around which the rotation will occur. A third parameter is the pivotPoint, which determines the center of the rotation. We set this point to get a nice caroussel effect. This is a Vector3D, which is a point in 3-dimensional space. In this case the _y Value has to be 0, since this is the axis of the rotation. Since the width of the stage is 550 pixel, we select 550 for the _x value of the Vector3D. This gives a rotation around the x-center of the movie.


		/*
We define a new variable y, which is the value of the y position divided by speed. Overall this
will determine the speed of the transition.
*/
			var y:int;
			var pvp:Vector3D;
			if (_alter == 0 || _alter == 2)
			{
				y=60/speed;
				pvp=new Vector3D(-500,0,500);
			}
			else
			{
				y=-60/speed;
				pvp=new Vector3D(500,0,-500);
			}
			imageHolder.transform.matrix3D.appendTranslation(0,0,0);
			imageHolder.transform.matrix3D.appendRotation (y,Vector3D.Y_AXIS,pvp);
		

We now have everything moving, but we need to stop it after one rotation. There are several ways to do that. Check also the other subclasses. Here we make use of the Matrix3D.rawData Vector, which has 16 numbers. When the rotation is finished the value, which we call rValue here, gets back to 1.000... . However, this is only the case in an ideal situation. therefore, we look for a value close to 1.0, which will give us our image in a nearly ideal position, which does not alter the other transitions. You can test all this by yourself to see what I mean.


		/*
Unlike for other transitions here we use the rawData value, which is a "Vector of 16 Numbers, 
where every four elements can be a row or a column of a 4x4 matrix" (Adobe). We use a value, which
is closest to 1.000. Again we need to have a certain number of counts pass so that the 
rValue is lower than 0.995.
*/
			rValue=imageHolder.transform.matrix3D.rawData[0];
			if (rValue>0.995 && count>10)
			{
				removeEventListener (Event.ENTER_FRAME,newTransition);
				count=0;
				imageHolder.width=imageWidth;
				imageHolder.height=imageHeight;
				for (var i=0; i<myXML.sub.length(); i++)
				{
					MovieClip(imageHolder.parent.getChildByName("_mc"+i)).mouseEnabled=true;
				}
			}
			count++;
		/*
When the alpha value of the image is 0, we now load a new image using the LoaderClassStatic class.
This class uses the same Loader object but unloads the previous image.
*/
			if (imageHolder.alpha==0)
			{
				lcs.initLoader (myURL,loadingComplete,imageHolder);
				_changed=false;
			}
		}
		/*
When loading is complete, we remove the Listener.
*/
		private function loadingComplete (event:Event):void
		{
			LoaderClassStatic.myDispatcher.removeEventListener (Event.COMPLETE,loadingComplete);
			trace ("completed");
		}
	}
}
		

And this concludes the tutorial.

Karthick.S commented on 11-29-2009:

Nice tutorial thanx a lot :)

Mail Form

Leave any comments here. Please enter a valid email.