Jun
11
Realistic Shadow Effects using Filters
I have another simple but neat, little tutorial here on Flash CS3 filters. This time I’m not using Tweens at all. Our effect is going to use the MouseEvent.MOUSE_MOVE event to create the illusion of a light source coming from our cursor.
To begin with we are going to make our Shadows class. This class is going to extend MovieClip, have a DropShadowFilter pre-applied to it and a public method to change the drop shadow filters distance and angle.
public static var All:Array;
protected var txtF:TextField;
protected var drop:DropShadowFilter;
protected var distance:Number;
protected var angle:Number;
protected var dropAlpha:Number;
protected var blurX:Number;
protected var blurY:Number;
public function Shadows() {
if(Shadows.All == null) Shadows.All = new Array();
distance = 0;
angle = 0;
dropAlpha = 1;
blurX = 0;
blurX = 0;
drop = new DropShadowFilter(distance, angle, 0, dropAlpha, blurX, blurY);
this.filters = [drop];
Shadows.All.push(this);
}
public function lightSource(X:Number, Y:Number):void {
var dx:Number = (this.x + (this.width/2))-X;
var dy:Number = (this.y + (this.height/2))-Y;
angle = (180 * Math.atan(dy/dx)) / Math.PI;
if(dx < 0){
angle += 180;
}
distance = Math.sqrt(dy*dy + dx*dx)/10;
dropAlpha = 10/distance;
blurX = Math.abs(dx/20);
blurY = Math.abs(dy/20);
drop = new DropShadowFilter(distance, angle, 0, dropAlpha, blurX, blurY);
this.filters = [drop];
}
}
I hope you can see what is going on in the code. I’m simply setting all my variables equal to 0 or 1, depending on what it’s for, and applying my filter in the constructor. Also note that I’m saving all my objects in a static array. This makes it easier to call all the lightSource() methods at once in a for loop later.
In the lightSource() method we have a little bit of math that you might be unfamiliar with.
My variables dy and dx stand for distance y or x and I’m setting them equal to the distance from the point given and the center of my ShadowObject.
angle is going to be the angle of the drop shadow and it needs to be in degrees. Math.atan() is called arc-tangent in the Trigonometry world and it gives your the value of the angle opposite the Y side of a right triangle in radians. If that doesn’t make sense, just know that it’s giving me that angle I need, but in the wrong units. I convert it by multiplying by 180 and dividing by PI. Math.atan() only returns a value between -pi/2 and pi/2 (-90 to 90 degrees) which only covers half a circle, so I have to check if we actually need the other side. And, that’s what my if() statement is for.
distance is calculated using the Pythagorean theorem C^2 = A^2 + B^2 (and then divided by 10 otherwise it’s just too much).
DropAlpha, blurX, and blurY are all set pretty clearly (blur has to be positive, thus the Math.abs() or absolute value).
Finally our function creates a new drop filter with our new values and applies it to our Shadow object.
Except for trying to remember the math involved, this one has been pretty easy so far, huh? Well then, let’s try using it in a project!
var str2 = new String("Media");
var letter:Shadows;
var newX:Number = 30;
var overLetter:TextField;
for(var i=0; i<str.length; i++) {
letter = new Shadows();
letter.x = newX;
letter.y = 80;
overLetter = new TextField();
overLetter.text = str.charAt(i);
overLetter.setTextFormat(new TextFormat("Georgia", 100, 0×0000FF, true));
overLetter.autoSize = TextFieldAutoSize.LEFT;
letter.addChild(overLetter);
addChild(letter);
newX += letter.width;
}
newX = 80;
for(i=0; i<str2.length; i++) {
letter = new Shadows();
letter.x = newX;
letter.y = 180;
overLetter = new TextField();
overLetter.text = str2.charAt(i);
overLetter.setTextFormat(new TextFormat("Georgia", 100, 0×0000FF, true));
overLetter.autoSize = TextFieldAutoSize.LEFT;
letter.addChild(overLetter);
addChild(letter);
newX += letter.width;
}
function changeLight(event:MouseEvent):void {
for(var i=0; i<Shadows.All.length; i++) {
Shadows.All[i].lightSource(stage.mouseX, stage.mouseY);
}
}
stage.addEventListener(MouseEvent.MOUSE_MOVE, changeLight);
So, there it is. I’m adding each letter to a different Shadow object so that their shadows move independently. I then update all the shadow light sources to the mouse’s X and Y coordinates every time the mouse moves. SO EASY!!
I have a few more ideas for cool effects that you can make with filters and I will probably post about them soon.
Download the Source Code for the example used in this post here: ShadowsSource.zip
Tags: DropShadowFilter, Filters




















June 11th, 2008 at 15:49
Wow! Very cool, thanks for the tutorial!
Joey - http://www.LeetWebmasters.com
June 12th, 2008 at 3:18
One problem: why is the shadow _over_ letters? Place cursor on the right side and look at ‘lic’ letters. :)
June 12th, 2008 at 12:03
Very cool, will be added to my site http://www.adsmap.net
Thanks!
June 12th, 2008 at 14:53
Leafnode, I noticed this problem. It’s because I wanted each letter to have it’s own shadow. And, since each shadow is at the same index as it’s parent movie clip, the shadows go over top anything that was added as a child earlier then it.
ClickPopMediaIf you wanted to avoid this (and I’ve tested this method) you can add everything a second time. For example, have the words ClickPop Media with shadows and then add the words again without shadows.
I felt that it wasn’t too big of a deal for my example and so I left it this way in order to keep the code simpler.
July 15th, 2008 at 14:00
i love this, u smashing it