Finally caved in and bought Essential ActionScript 2.0. For years now i've been wanting to learn more on object oriented coding. Actionscript 2.0 was a strange beast to me, in which i happily coded oldstyle. No more! Here is the code for the class, which you need to save in a seperate ColorPicker.as file. I simply saved it next to the .fla file, so no need to import it. If you use the ColorPicker class, Flash simply incorporates it. In the .fla file i put in a textfield and a movieclip, added them to the ColorPickerBroadcaster and wrote an onChangeColor function. The code in the .fla file is:
import flash.geom.Transform; import flash.geom.ColorTransform; //ColorPicker(target:String, depth:Number, xPos:Number, yPos:Number, rows:Number, w:Number, h:Number) var picker:ColorPicker = new ColorPicker("picker",100,40,40,36,10,10); ColorPicker.ColorPickerBroadcaster.addListener(_root.t); ColorPicker.ColorPickerBroadcaster.addListener(_root.mc); _root.t.onColorChange = function(colorValue:Number){ this.text = colorValue; } _root.mc.onColorChange = function(colorValue:Number){ var colorTrans:ColorTransform = new ColorTransform(this); colorTrans.rgb = colorValue; var trans:Transform = new Transform(this); trans.colorTransform = colorTrans; }
The flash.geom.Transform and flash.geom.ColorTransform i used for the first time. I copied and pasted code from the help files, still another area i need to get to grips with.
In the class i was having most trouble with the broadcasting. It seemed to me a sensible and adaptable way of using the colorValues, but the different methods of declaring variables in a class were a bit fuzzy. In the end i had to declare the ColorPickerBroadcaster as a public static var. Static means you can access the variable (or maybe better: method or property) through the class itself. Very similar to the Math class.
Finally i added some rollover effects. I did try to get a 'selected' effect as well, but that was a bit more tricky, and, being a little tired, i decided to leave it out. I'm sure there are better ways of doing this, and maybe i should have made the class more modular, but for now i'm quite happy with it.
class ColorPicker { //the hexArray gives the building blocks to fill the websafeColors Array //you could actually just type the array, but that is a very boring job private var hexArray:Array = new Array("00","33","66","99","CC","FF"); private var prefix:String = "0x"; //the rr, gg and bb vars are counters, i named them to make clear what they're supposed to do private var rr:Number = 0; private var gg:Number = 0; private var bb:Number = 0; private var row:Number = 0; //ws is a counter for going through the websafecolor array //because i use a double nested loop, there isn't a single counter going from 0 - 215 //its ws's job to do that, it also provides the depth for the button private var ws:Number = 0; //initialize the websafeColors array private var websafeColors:Array = new Array(); //not sure why i made this static, i do think i copied it out of the book private static var inited:Boolean = false; //the ColorPickerBroadcaster is a static object which you can reference through the class itself //ColorPicker.ColorPickerBroadcaster.addListener(mc); //the buttons, when clicked, make the object broadcast an 'onColorChange' event with the color as parameter //this should make implementation quite easy public static var ColorPickerBroadcaster:Object = new Object(); //contructor function //target = name movieclip to hold the colorpicker //depth in which you want the colorpicker to be placed //xPos and yPos: _x and _y position //rows: number of rows: defaults to 36, which gives 6 columns //best options are multiples of 6 //w and h are the width of the buttons, defaults to 10 public function ColorPicker(target:String, depth:Number, xPos:Number, yPos:Number, rows:Number, w:Number, h:Number){ if(!inited){ buildWebsafeColors(); } AsBroadcaster.initialize(ColorPickerBroadcaster); if(rows == undefined){ rows = 36; var columns = 6; } else { var columns:Number = websafeColors.length / rows; } if(w == undefined){ w = 10; } if(h == undefined){ h = 10; } _root.createEmptyMovieClip(target,depth); var mc:MovieClip = _root[target]; mc._x = xPos; mc._y = yPos; for(var row:Number = 0; row < rows; row++){ for(var column:Number = 0; column < columns; column++){ drawButton(mc, ws, websafeColors[ws], column * w, row * h, w, h); ws++; } } } //build array of websafe color values //this has to be done before buttons are build, so there is a little built in check //at the end of the function 'inited' is set to true private function buildWebsafeColors():Void{ for(rr = 0; rr < 6; rr++){ var tmpColor = "0x"; var tmpColor1 = tmpColor + hexArray[rr]; for(gg = 0; gg < 6; gg++){ var tmpColor2 = tmpColor1 + hexArray[gg]; for(bb = 0; bb < 6; bb++){ var tmpColor3 = tmpColor2 + hexArray[bb]; websafeColors.push(tmpColor3); } } } inited = true; } private function drawButton(target:Object, depth:Number, btnColor:Number, xPos:Number, yPos:Number, w:Number, h:Number):Void{ //at first i had the target typed as a movieclip //i retyped it as an Object, because i wanted to add a custom property: colorValue //the onrelease action can than look up the property and pass it on to the broadcaster target.createEmptyMovieClip("btn" + depth, depth); var btn:MovieClip = target["btn" + depth]; //i don't like to see the handcursor when i go over the buttons //there is a rollover state which provides feedback //most applications dont show a handcursor when you select a colour btn.useHandCursor = false; btn._x = xPos; btn._y = yPos; btn.beginFill(btnColor); btn.lineTo(w,0); btn.lineTo(w,h); btn.lineTo(0,h); btn.lineTo(0,0); btn.endFill(); btn.colorValue = btnColor; //the onrelease event makes the broadcaster send out the colorvalue btn.onRelease = function(){ ColorPicker.ColorPickerBroadcaster.broadcastMessage("onColorChange", this.colorValue); } //simple rollover effect //maybe add a onColorRollOver broadcastmessage, so the textfield shows the colorvalue on rollover //the rolover effect is done in a temporary movieclip, so it can be easily removed in the onRollOut event //first i thought i could use clear, but that would wipe out the entire movieclip! btn.onRollOver = function(){ this.createEmptyMovieClip("tmp",1); this.tmp.lineStyle(0,0xFFFFFF); this.tmp.lineTo(this._width - 1,0); this.tmp.lineTo(this._width - 1,this._height - 1); this.tmp.lineTo(0,this._height - 1); this.tmp.lineTo(0,0); } btn.onRollOut = function(){ this.tmp.removeMovieClip(); } } }