views:

547

answers:

2

For a project I'm working on I'm trying to create a Flash file with a constantly color-shifting gradient that fills up the entire browser window. For a better explanation please see the following link:

GradientTest Example

Don't worry about the moving balls, those are just there to challenge the frameRate of the movie, which has a maximum of 60. If you look at the background you can see the gradient effect I'm referring to.

The method I'm currently using to create the gradient animation is a simple shape tween on the Flash timeline that tweens between shapes with different gradient colors. I'm definitely not achieving the performance I want using this technique.

So that's a long-winded way of asking what people think would be a better way to create such a color-shifting gradient while getting better performance? Some examples might be through bitmapData or using PixelBender, but I'm not versed enough in these techniques to know which would get me the best performance. Any help would be appreciated!

NOTE: In the comments below is a link to all of the project files used in the example posted above.

UPDATES:

I've posted an additional version of the example using zkarcher's code in place of my timeline-based gradient animation to compare the performance of each. It should be noted that my version (v1) is always playing the gradient while the code-based version (v2) only plays the gradient animation for 5 seconds each time you click.

As a new user I'm only allowed one link per post so please forgive the raw URLs

http://www.chrismalven.com/experiments/GradientTest/
http://www.chrismalven.com/experiments/GradientTest_v2/


For those interested in using a version of zkarcher's gradient-tweening code with TweenLite/TweenMax, replace the Tweener reference with the code below and be sure to import the TweenMax ColorTransform Plugin as well:

// Load the TweenMax Class Libraries
import gs.*; 
import gs.easing.*;
import gs.plugins.*;
TweenPlugin.activate([ColorTransformPlugin]);

TweenMax.to(
    bmp, // Object to tween
    changeSpeed, // Duration of the Tween
    {colorTransform:
     {
     redMultiplier: (o2.r-o1.r)/255.0,
     greenMultiplier: (o2.g-o1.g)/255.0, 
     blueMultiplier: (o2.b-o1.b)/255.0,  
     alphaMultiplier: 1,
     redOffset: o1.r,
     greenOffset: o1.g,
     blueOffset: o1.b,
     alphaOffset: 0
     },
    ease:Quad.easeOut,
    }
);
+2  A: 
// Here's how I did it. I wrote & tested this in Flash CS4.

// I rambled about this technique in my blog:
//    http://blog.zacharcher.com/2007/10/13/understanding-colormatrixfilter/
// The goal is to create a simple black-and-white gradient, then tween its ColorTransform,
// rather than redraw a new gradient every frame.

// I'm going to use Tweener as my tweening engine because I'm used to it.
// Download from here: http://code.google.com/p/tweener/downloads/list
import caurina.transitions.Tweener;
import caurina.transitions.properties.ColorShortcuts;
ColorShortcuts.init();

// First, create a Shape with a gradient fill.
var shp:Shape = new Shape();
var mtx:Matrix = new Matrix();  // This matrix is needed for Shape.beginGradientFill()
mtx.createGradientBox( stage.stageWidth, stage.stageHeight, Math.PI/2 );
with( shp.graphics ) {
    beginGradientFill( GradientType.LINEAR, [0x000000,0xffffff], [1,1], [0,255], mtx );
    drawRect( 0, 0, stage.stageWidth, stage.stageHeight );
    endFill();
}

// Draw the Shape inside some BitmapData.
var bData:BitmapData = new BitmapData( stage.stageWidth, stage.stageHeight, false, 0x000000 );
bData.draw( shp );

// Create a Bitmap to display the BitmapData, and add it to the stage.
var bmp:Bitmap = new Bitmap( bData );
addChild( bmp );

// For testing purposes: Set up a mouse click listener. When the user clicks, tween to new colors.
stage.addEventListener( MouseEvent.CLICK, onClick );

function onClick( e:MouseEvent ) :void {
    // Choose two colors at random
    var c1:int = 0xffffff * Math.random();
    var c2:int = 0xffffff * Math.random();
    trace("Now tweening to:", c1.toString(16), c2.toString(16) );
    colorChange( c1, c2 );
}

// This function supports tweening the gradient to ANY TWO COLORS.
// If you just want to tint a gradient, then you can use less scary code,
// but you didn't specify that ;)
function colorChange( c1:uint, c2:uint ) :void {
    // Split the incoming color uint's into RGB values, ranging from 0..255
    var o1:Object = {
     r: (c1 & 0xff0000) >> 16,
     g: (c1 & 0x00ff00) >> 8,
     b:  c1 & 0x0000ff
    };
    var o2:Object = {
     r: (c2 & 0xff0000) >> 16,
     g: (c2 & 0x00ff00) >> 8,
     b:  c2 & 0x0000ff
    };

    // Using these values, create our sweet ColorTransform.
    // This will "map" the black and white pixels to the desired colors.
    // The aforementioned blog post explains this math:
    var ct:ColorTransform = new ColorTransform( (o2.r-o1.r)/255.0, (o2.g-o1.g)/255.0, (o2.b-o1.b)/255.0, 1,  o1.r, o1.g, o1.b, 0 );

    // Start the tween.
    Tweener.addTween( bmp, {_colorTransform:ct, time:1.0, transition:"easeOutQuad"} );
}

// Hope this helps...
zkarcher
This is a really cool technique for creating a gradient transition. Thanks for posting it. For those TweenLite users out there you can make zkarcher's code work by using the changes I added to my original question. Unfortunately, as evidenced by the dual examples, this technique offers almost exactly the same performance as my original timeline-animation method.
cmal
Ah, that's a bummer that my technique didn't increase the frame rate. Sorry... I tried my best!
zkarcher
A: 

Hey there, i am quite new to ActionScript, could you describe how to set up 2 pre selected colors to tween a gradient to instead of "random" ones. My Goal would be to use this class as a dynamic background creater and i would like to have different gradient backgrounds on different pages.

thanks in advance!

Roman Mueller