English 中文(简体)
Best method to scale DropShadows in AS3?
原标题:

I m creating a flash application that makes use of both the dropShadow filter and scaling of various sprites.

And therein lies the problem:

This filter supports Stage scaling. However, it does not support general scaling, rotation, and skewing. If the object itself is scaled (if scaleX and scaleY are set to a value other than 1.0), the filter is not scaled.

By happenstance the lack of rotation support is beneficial to me, but I really badly need the scaling to work. What s the best method for doing this?

Can I extend the DropShadow object and "make it" update?

Shall I make my own custom object that just recreates itself with a new .distance value to match the zoom level?

What s the best method to use (with performance in mind)?

最佳回答

With performance in mind, you can make use of a Bitmap and draw the original sized container with its DropShadowFilter onto it. This way, the filter will scale and Flash won t even have to recalculate the rendering of the drop shadow.

Example:

// We need to use this container as the source for the Bitmap.
var sample:Sprite = new Sprite();


// Sample object with DropShadowFilter applied.
var rect:Sprite = new Sprite();
rect.x = rect.y = 10;
rect.graphics.beginFill(0xCC0000);
rect.graphics.drawRect(0, 0, 50, 50);
rect.graphics.endFill();
rect.filters = [new DropShadowFilter()];
sample.addChild(rect);


// Create our Bitmap.
var bitmap:Bitmap = new Bitmap();

bitmap.x = bitmap.y = 100;
bitmap.bitmapData = new BitmapData(sample.width + 20, sample.height + 20, true);
bitmap.bitmapData.draw(sample);
bitmap.scaleX = bitmap.scaleY = 0.5;

addChild(bitmap);
问题回答

Since a filter doesn t scale, its parameter values must always correspond to pixel units. Therefore, you simply have to scale the filter values the same as the object. To do so, just translate a unit vector (length==1) in the objects s coordinate system to the global coordinate system and the distance will be your global scaling factor for the object s filters.

Every time your object moves or scales, alter any filter values that should scale and reapply the filters. Here is an example document class showing a square with glow and drop shadow filters scaling with it while it s nested in another container that s scaled as well. I also added a stage resize listener to keep the square in the center of the stage.

Paste this into the actions on the main timeline of a new document and run it. Notice that the drop shadow s distance and size scale, and the glow filter s blur scales as well. You could even add the math to account for rotation when you have different x and y blur values.

import flash.display.Sprite;
import flash.filters.GlowFilter;
import flash.events.Event;
import flash.display.StageScaleMode;
import flash.utils.getTimer;
import flash.geom.Point;
import flash.filters.DropShadowFilter;

//Fix the scale of the stage
stage.scaleMode = flash.display.StageScaleMode.NO_SCALE;
stage.frameRate = 60;

//Create a small green square centered at the origin
var r:Sprite = new Sprite();
r.graphics.beginFill( 0x00ff00 );
r.graphics.drawRect( -5, -5, 10, 10 );
r.graphics.endFill();

//Nest it in a container
var container:Sprite = new Sprite();
container.addChild( r )
addChild( container );

//Apply a glow filter
var GLOW_BLUR:Number = 10;
var SHADOW_DIST:Number = 5;
var SHADOW_BLUR:Number = 2;
var dropshadow:DropShadowFilter = new DropShadowFilter( SHADOW_DIST, 45, 0, 1, SHADOW_BLUR, SHADOW_BLUR, 1, 3 ); //new GlowFilter( 0x000000, 0.5, GLOW_BLUR, GLOW_BLUR, 2, 3 );
var glow:GlowFilter = new GlowFilter( 0x0000ff, 1, GLOW_BLUR, GLOW_BLUR, 1, 3 ); //new GlowFilter( 0x000000, 0.5, GLOW_BLUR, GLOW_BLUR, 2, 3 );
r.filters = [glow,dropshadow];

addEventListener( Event.ENTER_FRAME, enterFrame, false, 0, true );
addEventListener( Event.RESIZE, stageResized, false, 0, true );
var t:int = getTimer();
stageResized( null );
function enterFrame( e:Event ):void
{
    var cycle_length:Number = 2000;
    var cycle:Number = (((getTimer() - t) % cycle_length) / cycle_length) * Math.PI * 2.0;
    var scale:Number = 2 + Math.sin( cycle );
    r.scaleX = r.scaleY = scale;
    container.scaleX = container.scaleY = scale * 2;
    container.rotation = cycle / (Math.PI / 180);

    var p0:Point = new Point( 0, 0 );
    var p1:Point = new Point( 1, 0 );
    p0 = r.localToGlobal( p0 );
    p1 = r.localToGlobal( p1 );
    var globalScale:Number = Point.distance( p0, p1 );

    dropshadow.blurX = dropshadow.blurY = SHADOW_BLUR * globalScale;
    dropshadow.distance = SHADOW_DIST * globalScale;
    glow.blurX = glow.blurY = GLOW_BLUR * globalScale;
    r.filters = [glow,dropshadow];
}
function stageResized( e:Event ):void
{
    container.x = (stage.stageWidth / 2);
    container.y = (stage.stageHeight / 2);
}

I am using dropShadow filter like this and scale, rotate, skew works fine:

var localFilters :Array = new Array();
localFilters.push( dropShadowFilter );

component.filters = localFilters;

after that if you do for example :

var m:Matrix = new Matrix();
m.scale( 1.5, 2 );

component.transform.matrix = m;

the dropShadow filter will be scaled.





相关问题
Disable button tooltip in AS3

I want to disable the tooltip on certain buttons. The tooltip manager seems to be an all or nothing solution. Is it possible to disable the tooltip for just one or two buttons?

Sorting twodimensional Array in AS3

So, i have a two-dimensional Array of ID s and vote count - voteArray[i][0] = ID, voteArray[i][1] = vote count I want the top 3 voted items to be displayed in different colors, so i have a 2nd Array -...

Virtual Tour using sketch up, ajax, flash technologies

I want to know if there are existing technology that make your 3d models in sketch into virtual tours, using either Ajax or Flash for web presentation. If there s none, which will be a good approach ...

AS3 try/catch out of memory

I m loading a few huge images on my flex/as3 app, but I can t manage to catch the error when the flash player runs out of memory. Here is the what I was thinking might work (I use ???? because i dont ...

Red5 Security Tutorial

I am looking for a step by step tutorial on securing Red5 from intrusion. This seems to be a question that comes up alot in a google search, but is never really answered in a way that makes sense to ...

Clipboard access using Javascript - sans Flash?

Is there a reliable way to access the client machine s clipboard using Javascript? I continue to run into permissions issues when attempting to do this. How does Google Docs do this? Do they use ...

visible property of DisplayObject

For example I have a hierarchy of movie clips. mc1 is a child of mc, and mc2 is a child of mc1. Turns out that when I set mc1.visible = false; mc2.visible stays true. Is that supposed to happen?...

热门标签