views:

310

answers:

4

I'm working on my first Flash project, and for my preloader I'd like to do a really simple gradient based on the percentage loaded. The preloader says "77% loaded...", where the number 77 is a dynamic text instance called percentLoaded. I'd like the textColor of percentLoaded to change on a gradient from #000000 to #FFFFFF, in gray-scale.

Therefore, I can't simply do:

percentLoaded.textColor=(currentValue/100)*0xFFFFFF;

This just converts the textColor to a multiple of FFFFFF, but outputs a color since it's not three separate components. Currently, here's what I've got:

percentLoaded.text=currentValue.toString();
percentLoaded.textColor=rgb2hex((currentValue/100)*255, (currentValue/100)*255, (currentValue/100)*255);

Where "rgb2hex" is a function defined within the class as such:

public function rgb2hex(r:Number, g:Number, b:Number) {
    return '0x'+(r << 16 | g << 8 | b).toString(16).toUpperCase();
}

It doesn't look like this is actually changing the color of the font though. I've imported flash.text.TextField and flash.display.MovieClip, but am not sure if I'm missing something else. Would this be easier to do with string concatenation? Or is there maybe something going on with currentValue/100 and passing that as a Number?

If curious, I found the code for rgb2hex here.

Thanks!

+1  A: 
percentLoaded.textColor = int((currentValue / 100) * 0xFF) * 0x010101;

The cast to an int before multiplying by 0x010101 is a must. 8 bit color values can only be integers between 0-255. If it's not within these bounds, the multiplication by 0x010101 could cause numbers to overflow from one color component(RR,GG,BB) to another (B->G, G->R). But they can also carry the other way if not an integer (R->G, G->B). I've assumed currentValue is any number between 0-100.

Consider this, with each digit it's own color component(in decimal):

5.0 * 111 = 555 = 5R, 5G, 5B
5.5 * 111 = 610.5 = 6R, 1G, 0.5B
Wallacoloo
+4  A: 
percentLoaded.textColor=(currentValue/100)*0xFFFFFF;

This is close.

To get a grayscale, you indeed need to have each component, but this can still be done by similar method of yours:

percentLoaded.textColor = uint((currentValue / 100) * 0xFF) * 0x010101;
LiraNuna
This doesn't work. try setting currentValue to 1. You get 0x28f5c. you need to cast ((currentValue / 100) * 0xFF) to an int before multiplying by 0x010101.
Wallacoloo
True, I forgot about that, fixed; thank you for noting that! The cast actually needs to go on the division result, since that's why it happens - Flash's `Number` class is an IEE float. Casting to uint should solve it.
LiraNuna
No, current value is between 0-100. If you cast after dividing, but before multiplying by 0xFF, you'll get a 0 or a 1. He wants full grayscale, not just black/white. And the problem does not arise from floating point inaccuracies. It's because your format (*0x010101) is essentially three fields (01, 01, 01). It's not expecting something in one field to be influenced by another field. But using a value greater than 255, allows a low field to influence a high field, and a value between to integers allows a high field to influence a lower one. Try 1.5*0x010101 to see what I mean.
Wallacoloo
My bad, been coding too much today :P
LiraNuna
Thanks for the responses, all. It didn't work at first and I didn't want to comment because I wasn't really sure what was going on. I understand it now, and it's a particularly elegant solution!EDIT: I'll implement this in my code later and mark it as an Answer once I'm sure it works.
Rockmaninoff
+1  A: 

If this works for you

percentLoaded.textColor=(currentValue/100)*0xFFFFFF;

Then you could just do

var percent = currentValue / 100;
percentLoaded.textColor = Math.floor(percent*0xFF) * 0x010101;
sberry2A
This doesn't work. try setting currentValue to 1. You get 0x28f5c. you need to cast to an int before multiplying by 0x010101.
Wallacoloo
@wallacoloo: Right you are, fixed.
sberry2A
+2  A: 

Hi Rockmaninoff,

You're in luck, I happen to have done this very recently in a project, only with different colours. Here is a function that will return a colour value between two other colours, based on a range of 0-1. I think the code is pretty self explanatory, but let me know if you run into any issues.

private function getBetweenColourByPercent(value:Number = 0.5 /* 0-1 */, highColor:uint = 0xFFFFFF, lowColor:uint = 0x000000):uint {
    var r:uint = highColor >> 16;
    var g:uint = highColor >> 8 & 0xFF;
    var b:uint = highColor & 0xFF;

    r += ((lowColor >> 16) - r) * value;
    g += ((lowColor >> 8 & 0xFF) - g) * value;
    b += ((lowColor & 0xFF) - b) * value;

    return (r << 16 | g << 8 | b);
}

Tyler.

Tyler Egeto
Thanks Tyler, this may actually be useful a little while down the line; I might choose to have the preloader text go between red and white, for example.
Rockmaninoff