« Anticipation Abstract Data Types »

September 08, 2003

Scripting color transitions

Did you ever need to fade from 0xC47D31 to 0x67DEF9 and have no idea where to start? Typically the timeline is used to tween color transisiton at author-time, but what do you do if you want to fade colors at run-time? The answer is here... take a look at the code below.

/*
Darron Schall
Sept. 8, 2003

Takes in an integer in and splits it up into is red, green, and blue parts
*/
function int_to_rgb(i) {
 	var r = (i & 0xFF0000) >> 16;
 	var g = (i & 0x00FF00) >> 8;
 	var b = i & 0x0000FF;
 	return {r:r, g:g, b:b};
}

/* 
Darron Schall
Sept. 8, 2003

Smoothly transitions a movie clip from one color to another
over a certain duration.
SIDE EFFECT: onEnterFrame is used to perform the loop,
calling this function will overwrite any existing onEnterFrame 
function.  A better alternative may be to make use of 
setInterval instead. */
MovieClip.prototype.fadeFromTo = function(start_val, stop_val, duration) {
 	/* We don't need to save the stop_color, so just 
 declare it as a local variable */
 	var stop_color = int_to_rgb(stop_val);
 
 	this.start_color = int_to_rgb(start_val);
 	this.duration = duration;
 	/* Delta is an object with 3 fields - each field specifies
  the amount of color shift from the start value to the stop value */
 	this.delta = {
  		r:(this.start_color.r-stop_color.r)/this.duration,
  		g:(this.start_color.g-stop_color.g)/this.duration,
  		b:(this.start_color.b-stop_color.b)/this.duration};
 	
 	/* Create a color object that refers to ourself, so we can change 
 our own color.  We create this object outside of the loop so it's 
 not continually created and destroyed*/
 	this.colorObj = new Color(this);
  
 	/* Start the ball rolling by changing our color initially, 
 before the loop. */
 	this.colorObj.setRGB(start_val);
 	
 	this.count = 1;
 	this.onEnterFrame = function() {
  		/* Construct an integer value from the 3 color parts.  
  We always add from the start color so that error in rounding
   doesn't get multiplied for each color change.  Doing things this 
  way makes the transition smoother and ensures that we 
  end up on the right color as well. */
  		var colorVal = ((this.start_color.r-this.count*this.delta.r) << 16)
  			+ ((this.start_color.g-this.count*this.delta.g) << 8)
  			+ (this.start_color.b-this.count*this.delta.b);
  		// Update our color value
  		this.colorObj.setRGB(colorVal);
  		if (this.count++ == this.duration) {
   			// Clean up after ourselves
   			delete this.start_color;
   			delete this.duration;
   			delete this.delta;
   			delete this.colorObj;
   			delete this.count;
   			delete this.onEnterFrame;
   		}
  	}
};

// Example usage:
some_mc.fadeFromTo(0xFFCC33, 0x990099, 45);

Let me know if you find this one useful. The same concept can be applied to TextFields as well to fade their background colors. Enjoy!

Comments

  • converted to a class file for AS 2.0. Only changed some targeting
    //========================

    class com.aol.comet.effects.ColorFader{
    //== Converted to AS 2.0 Class by Christopher Flinders 2004
    /*
    Darron Schall
    Sept. 8, 2003
    Smoothly transitions a movie clip from one color to another
    over a certain duration.
    SIDE EFFECT: onEnterFrame is used to perform the loop,
    calling this function will overwrite any existing onEnterFrame
    function. A better alternative may be to make use of

    // Example usage:
    //fadeFromTo(_root.box, 0xFFCC33, 0x990099, 45);


    ===========================================
    ===========================================*/

    function ColorFader(){
    //== Init
    }

    //Takes in an integer in and splits it up into is red, green, and blue parts

    function int_to_rgb(i) {
    var r = (i & 0xFF0000) >> 16;
    var g = (i & 0x00FF00) >> 8;
    var b = i & 0x0000FF;
    return {r:r, g:g, b:b};
    }


    function fadeFromTo(targetMC, start_val, stop_val, duration) {
    /* We don't need to save the stop_color, so just
    declare it as a local variable */
    var stop_color = int_to_rgb(stop_val);

    targetMC.start_color = int_to_rgb(start_val);
    targetMC.duration = duration;
    /* Delta is an object with 3 fields - each field specifies
    the amount of color shift from the start value to the stop value */
    targetMC.delta = {
    r:(targetMC.start_color.r-stop_color.r)/targetMC.duration,
    g:(targetMC.start_color.g-stop_color.g)/targetMC.duration,
    b:(targetMC.start_color.b-stop_color.b)/targetMC.duration};

    /* Create a color object that refers to ourself, so we can change
    our own color. We create targetMC object outside of the loop so it's
    not continually created and destroyed*/
    targetMC.colorObj = new Color(targetMC);

    /* Start the ball rolling by changing our color initially,
    before the loop. */
    targetMC.colorObj.setRGB(start_val);

    targetMC.count = 1;
    targetMC.onEnterFrame = function() {
    /* Construct an integer value from the 3 color parts.
    We always add from the start color so that error in rounding
    doesn't get multiplied for each color change. Doing things this
    way makes the transition smoother and ensures that we
    end up on the right color as well. */
    var colorVal = ((this.start_color.r-this.count*this.delta.r) << 16)
    + ((this.start_color.g-this.count*this.delta.g) << 8)
    + (this.start_color.b-this.count*this.delta.b);
    // Update our color value
    this.colorObj.setRGB(colorVal);
    if (this.count++ == this.duration) {
    // Clean up after ourselves
    delete this.start_color;
    delete this.duration;
    delete this.delta;
    delete this.colorObj;
    delete this.count;
    delete this.onEnterFrame;
    }
    }
    };


    }