ColorPicker Class

 

In this chapter I present my ColorPicker class that can be used by anyone who finds it to be helpful. This class provides a simple color picker as a graphical interface that can be used to interactively determine the color of another display object in your Flash application, just the same way as in common graphic programs: Each ColorPicker object contains two charts that can be manipulated by your mouse. The chart on the right is used to select the hue of a color (the selected hue is indicated by the two arrows). Depending on that hue the left chart will automatically be updated. This color chart allows the user to choose the values for the remaining two dimensions in the HSL system: The saturation (x-axis) and the lightness (y-axis). The resulting color code (as a combined triplet of hexadecimal intensity values for the three channels of your monitor) is displayed at the bottom of the ColorPicker object and is also continuously updated during the selection process, as well as the adjacent small patch that displays the currently selected color.

 

Demonstration

For a demonstration of the functionality of the ColorPicker class, see the following example application: In this example two instances of the ColorPicker class are implemented that can be used to determine the two colors of a checkerboard pattern. The respective color will be applied to that pattern as soon as the mouse button is released.

 

 

 

Embedding of the ColorPicker class

In order to use my ColorPicker class in your own Flash project you first have to copy the following code and save it in a file with the name “ColorPicker.as”. For demonstration purposes I didn't specify a certain package path here, that means that you have to put that file in the same folder as your Flash project (otherwise it's up to you to define your own path). I will not explain the code of the class here, but in case you have any questions about it, don't hesitate to leave a comment on this page.

 


package
{
	/*
	 * @author Gunnar Wendt 2012
	 * @version 1.0
	 * 
	 * www.worldwidewendt.com
	 *
	 */
	 
	 
	import flash.display.Sprite;
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.events.MouseEvent;
	import flash.text.TextField;
	import flash.text.TextFormat;
	
	public class ColorPicker extends Sprite
	{
		private var hueDown:Boolean = false;
		private var colorDown:Boolean = false;
		public var colorResult:uint = 0;
		private var h:Number = 1.0;
		private var s:Number = 0.5;
		private var l:Number = 0.5;
		public var ColorChartData:BitmapData = new BitmapData(100,100,false,0x000000);
		public var ColorChartImage:Bitmap = new Bitmap(ColorChartData);
		public var ColorChartContainer:Sprite = new Sprite;
		public var HueChartData:BitmapData = new BitmapData(25,100,false,0x000000);
		public var HueChartImage:Bitmap = new Bitmap(HueChartData);
		public var HueChartContainer:Sprite = new Sprite;

		
		public var ColorPointer:Sprite = new Sprite();
		public var colorDisplay:TextField = new TextField();
		public var HueBar:Sprite = new Sprite();

			
		public function ColorPicker(colh:Number = 1.0,cols:Number = 0.5,coll:Number = 0.5)
		{	
			if(colh < 0)
				colh = 0;
			if(colh > 1)
				colh = 1;
			if(cols < 0)
				cols = 0;
			if(cols > 1)
				cols = 1;
			if(coll < 0)
				coll = 0;
			if(coll > 1)
				coll = 1;
				
			h = colh;
			s = cols;
			l = 1 - coll;
			
			drawPicker(h);		
			setListeners();										
		}
		
		private function drawPicker(hue:Number):void
		{
		
			this.graphics.lineStyle(1,0x888888);
			this.graphics.beginFill(0x333333);
			this.graphics.drawRoundRect(0,0,140,140,8);
			
			colorDisplay.type = "dynamic";
			colorDisplay.wordWrap = true;
			colorDisplay.border = true;
			colorDisplay.background = 0xCCCCCC;
			colorDisplay.width = 70;
			colorDisplay.height = 25;
			colorDisplay.x = 5;
			colorDisplay.y = 110;
					
			updateColorChart(hue);
			
			drawHueChart();

			ColorChartContainer.addChild(ColorChartImage);
			ColorChartContainer.x = 5;
			ColorChartContainer.y = 5;
			this.addChild(ColorChartContainer);
			HueChartContainer.addChild(HueChartImage);
			HueChartContainer.x = 110;
			HueChartContainer.y = 5;
			this.addChild(HueChartContainer);
			
			
			this.addChild(colorDisplay);
			
			ColorChartContainer.mouseChildren = false;
			
			HueChartContainer.mouseChildren = false;
			drawCurrentColor(uint(HSLtoRGB(h,s,l)));
			setDisplay(HSLtoRGB(h,s,l));
			
			///HUE POINTER
			HueBar.graphics.beginFill(0xFFFFFF);
			HueBar.graphics.moveTo(-4,-3);
			HueBar.graphics.lineTo(-4,3);
			HueBar.graphics.lineTo(0,0);
			HueBar.graphics.moveTo(29,-3);
			HueBar.graphics.lineTo(29,3);
			HueBar.graphics.lineTo(25,0);
			HueBar.graphics.endFill();
			HueChartContainer.addChild(HueBar);
			drawHueBar((1-h)*100);
			
			///COLOR POINTER
			var rad:int = 3;
			var xpos:int = 0;
			var ypos:int = 0;
			
			ColorPointer.graphics.lineStyle(1,0xFFFFFF);
			ColorPointer.graphics.moveTo(xpos,ypos-rad);
			ColorPointer.graphics.curveTo(xpos+rad,ypos-rad,xpos+rad,ypos);
			ColorPointer.graphics.lineStyle(1,0x000000);
			ColorPointer.graphics.curveTo(xpos+rad,ypos+rad,xpos,ypos+rad);
			ColorPointer.graphics.lineStyle(1,0xFFFFFF);
			ColorPointer.graphics.curveTo(xpos-rad,ypos+rad,xpos-rad,ypos);
			ColorPointer.graphics.lineStyle(1,0x000000);
			ColorPointer.graphics.curveTo(xpos-rad,ypos-rad,xpos,ypos-rad);
			ColorPointer.cacheAsBitmap = true;
			ColorChartContainer.addChild(ColorPointer);
			drawPointer(s*100,l*100);
				
		}
		
		private function toHex(num:uint):String
		{
			var firstDigit:uint = Math.floor(num/16);
			var secondDigit:uint = num%16;
	
			var hexDigits:Array = ["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"];
	
			var str:String = hexDigits[firstDigit]+hexDigits[secondDigit];
	
			return str;	
		}
		
		private function colorHex(red:uint,green:uint,blue:uint):String
		{
			var resStr:String = "0x"+toHex(red)+toHex(green)+toHex(blue);

			return resStr;	
		}
		
		private	function HuetoRGB(v1:Number, v2:Number, vH:Number):Number
		{
			if(vH < 0)
			{
				vH += 1;
			}
			else if(vH > 1)
			{
					vH -= 1;
			}
			if((6*vH) < 1)
			{
				return v1 + (v2 - v1) * 6 * vH;
			}
			if((2 * vH) < 1)
			{
				return v2;
			}
			if((3 * vH) < 2)
			{
				return v1 + (v2 - v1) *((2/3) - vH)* 6;
			}
	
			return v1;	
		}
		
		private function HSLtoRGB(h:Number, s:Number, l:Number):String
		{
			var r,g,b:uint;
			var v1, v2:Number;
			l = 1-l;
			if(s==0)
			{
				r = l * 255;
				g = l * 255;
				b = l * 255;
			}
			else
			{
				if(l < 0.5)
				{
					v2 = l * (1 + s);
				}
				else
				{
					v2 = (l + s) - (s * l);
				}
				v1 = 2 * l - v2;
		
				r = uint(255 * HuetoRGB(v1,v2,h+(1/3)));
				g = uint(255 * HuetoRGB(v1,v2,h));
				b = uint(255 * HuetoRGB(v1,v2,h-(1/3)));
		
			}
			return colorHex(r,g,b);
	
		}
		
		
		private function updateColorChart(hue:Number):void
		{
	
			for(var i:uint = 0;  i < 100; i++)
			{
				for(var j:uint = 0; j < 100; j++)
				{
					ColorChartData.setPixel(i,j,uint(HSLtoRGB(hue,i/100,j/100)));
				}
			}
		}
		
		private function drawHueChart():void
		{
			for(var k:uint = 0; k < 25; k++)
			{
				for(var l:uint = 0; l < 100; l++)
				{
					HueChartData.setPixel(k,l,uint(HSLtoRGB(1-l/100,0.8,0.5)));
				}
			}
		}
		
		
		////LISTENERS
		function setListeners():void
		{
			this.ColorChartContainer.addEventListener(MouseEvent.MOUSE_MOVE,updateColor);
			this.ColorChartContainer.addEventListener(MouseEvent.MOUSE_DOWN,downColor);
			this.ColorChartContainer.addEventListener(MouseEvent.MOUSE_UP,upColor);
			this.ColorChartContainer.addEventListener(MouseEvent.MOUSE_OUT,upColor);
			this.HueChartContainer.addEventListener(MouseEvent.MOUSE_MOVE,getHue);
			this.HueChartContainer.addEventListener(MouseEvent.MOUSE_DOWN,downHue);
			this.HueChartContainer.addEventListener(MouseEvent.MOUSE_UP,upHue);
			this.HueChartContainer.addEventListener(MouseEvent.MOUSE_OUT,upHue);
		}
		
		private function updateColor(event:MouseEvent):void
		{	
			if(colorDown)
			{
				s = ColorChartContainer.mouseX/100;
				l = ColorChartContainer.mouseY/100;
				var myColor:uint = uint(HSLtoRGB(h,s,l));
				drawPointer(ColorChartContainer.mouseX,ColorChartContainer.mouseY);
				
				setDisplay(HSLtoRGB(h,s,l));
				drawCurrentColor(myColor);
				colorResult = myColor;
			}

		}
		
		private function downColor(event:MouseEvent):void
		{
			colorDown = true;
			s = ColorChartContainer.mouseX/100;
			l = ColorChartContainer.mouseY/100;
			var myColor:uint = uint(HSLtoRGB(h,s,l));
			drawPointer(ColorChartContainer.mouseX,ColorChartContainer.mouseY);
			setDisplay(HSLtoRGB(h,s,l));
			drawCurrentColor(myColor);
		}
		
		private function upColor(event:MouseEvent):void
		{
			colorDown = false;
		}
		

		
		private function getHue(event:MouseEvent):void
		{
			if(hueDown)
			{
				h = 1 - event.currentTarget.mouseY/100;
				updateColorChart(h);
				drawCurrentColor(uint(HSLtoRGB(h,s,l)));
				setDisplay(HSLtoRGB(h,s,l));

				HueBar.y = event.currentTarget.mouseY;
				
			}	
		}
		
		private function downHue(event:MouseEvent):void
		{
			hueDown = true;
			h = 1 - event.currentTarget.mouseY/100;
			updateColorChart(h);
			drawCurrentColor(uint(HSLtoRGB(h,s,l)));
			setDisplay(HSLtoRGB(h,s,l));

			HueBar.y = event.currentTarget.mouseY;
		
		}
		
		private function upHue(event:MouseEvent):void
		{
			hueDown = false;
		}
	
		
		private function setDisplay(col:String):void
		{
			var textFormat:TextFormat = new TextFormat();
			textFormat.color = 0x222222;
			textFormat.font = "Arial";
			colorDisplay.text = col;
			colorDisplay.setTextFormat(textFormat);
			
		}
		
		private function drawPointer(xpos:int, ypos:int):void
		{
			ColorPointer.x = xpos;
			ColorPointer.y = ypos;
	
		}
		
		private function drawHueBar(ypos:int):void
		{
				
			HueBar.y = ypos;
			
		}
		
		private function drawCurrentColor(col:uint):void
		{
			var CurrentColorData:BitmapData = new BitmapData(55,25,false,col);
			var CurrentColorImage:Bitmap = new Bitmap(CurrentColorData);
			CurrentColorImage.x = 80;
			CurrentColorImage.y = 110;
			
			this.addChild(CurrentColorImage);
			colorResult = col;
			
	
		}
		
		public function get getColor():uint
		{
			return colorResult;
		}
		
		public function get getH():Number
		{
			return h;
		}
		
		public function get getS():Number
		{
			return s;
		}
		
		public function get getL():Number
		{
			return l;
		}
		
	///END CLASS	
	}
///END PACKAGE	
}

 

How to use the ColorPicker class in your own project

The first step to use the ColorPicker class in your own project is to import that class: import ColorPicker;. Once added to your project you can create instances of the ColorPicker object in the usual way. In order to demonstrate the usage of that class I added the code that I used for the example: I created two instances of the ColorPicker object (myCP1 and myCP2), each responsible for one of the two colors of the checkerboard pattern. Calling the constructor of the ColorPicker class (new ColorPicker()) you can optionally initialize the instance with a start color using relative values [0-1] for the three color components in the order hue, saturation, and lightness (otherwise some default values are used). Since the ColorPicker class extends the Sprite class you can place each instance by means of the x and y property. Finally, you have to add each instance to the display list by calling the addChild() method, passing the instance name as argument. So far, these are the general steps to place a ColorPicker object in your scene.

This already looks quite nice, however, in order to use the functionality of that class one has to link the ColorPicker object to a mouse event and to the display object whose color shall be affected by the settings of the ColorPicker. Actually, there may be several ways to do that but I will report only the one I used for this example:
My checkerboard consists of two Sprites (mySprite1 and mySprite2), one as a huge square serving as the background, and another that contains numerous small squares to build that structured pattern. Each time the color of one of the checkerboard elements is to be changed a function will be called that applies the new color to the respective element (updateChecker(color_1, color_2)). As arguments we will pass the current color codes that are represented by the two ColorPicker instances. To receive the current color code that is represented by the ColorPicker object one has to call the class specific property getColor, in the example it is: myCP1.getColor, or myCP2.getColor, respectively. (For other pruposes it is also possible to get the relative values for the hue, the saturation, and the lightness. The related properties are: getH, getS, and getL.) So, the function updateChecker will be called each time the color in one of the ColorPicker instances has changed. Hence, both ColorPicker instances will be linked to the same mouse event by use of the addEventListener() method. And in my example, both instances are actually linked to the same event handler named updateColor that is called after a mouse click occurred. Well, and this is roughly how it works – quite simple, isn't it?

 


import ColorPicker;
import flash.events.MouseEvent;
import flash.display.*;

var myCP1:ColorPicker = new ColorPicker(0.35,0.5,0.6);
myCP1.x = 20;
myCP1.y = 20;
addChild(myCP1);

var myCP2:ColorPicker = new ColorPicker(0.5,0.7,0.3);
myCP2.x = 20;
myCP2.y = 180;
addChild(myCP2);


var mySprite1:Sprite = new Sprite();
mySprite1.x = 200;
mySprite1.y = 20;
addChild(mySprite1);

var mySprite2:Sprite = new Sprite();
mySprite2.x = 200;
mySprite2.y = 20;
addChild(mySprite2);


updateChecker(myCP1.getColor,myCP2.getColor);


myCP1.addEventListener(MouseEvent.CLICK,updateColor);
myCP2.addEventListener(MouseEvent.CLICK,updateColor);

function updateColor(event:MouseEvent):void
{
	updateChecker(myCP1.getColor,myCP2.getColor);
}

function updateChecker(col1:uint,col2:uint):void
{
	var l:int = 30;
	
	mySprite1.graphics.beginFill(col1);
	mySprite1.graphics.drawRect(0,0,300,300);
	mySprite1.graphics.endFill();
	
	mySprite2.graphics.beginFill(col2);
	for(var i:int = 0; i < 10; i++)
	{
		for(var j:int = 0; j < 10; j++)
		{
			if((i+j)%2 == 0)
			{
				mySprite2.graphics.drawRect(i*l,j*l,l,l);	
			}
		}
	}
	mySprite2.graphics.endFill();
	
}

 

 

© 2012 G. Wendt



Write a comment
Name: Note: Your email address will not be displayed on this site nor otherwise published!
Email:
Comment:
Anti-Spam:
Color & Font
Color tool

You have difficulties finding a balanced color combination and appropriate font formats for your website?


Use the tool Color & Font on this website in order to interactively create the color and font properties of your own site. The results of your settings can be easily included as CSS listing in your web project.

Archive
MTWTFSS
1234567
891011121314
15161718192021
22232425262728
2930