Hier geht es um das Einfärben oder um Farbveränderungen von MC- oder Sprite-Instanzen mit Flash Actionscript 3. Man benötigt wie in AS2 auch hier ein ColorTransform Object.
Siehe dazu auch die AS3 Referenzen
flash.geom.ColorTransform
flash.geom.Transform
flash.display.DisplayObject.transform
Farben können als uint oder hex Werte definiert werden. Siehe dazu auch folgenden Tipp im Netz.
Zum Thema RGB und Farbmodelle hab ich auch einges geschrieben.
Umrechnungen in meinem AS2 Tipp
Beispiel | |||||||
wert3 | Wert2 | Wert1 | |||||
324 | 200 | 430 | 324.200.430 | ||||
wert3 x1.000.000 | + | wert2 x 1000 | + | wert1 | |||
324.000.000 | + | 200.000 | + | 430 | = | 324.200.430 | |
Farbwert | |||||||
Rot | Grün | Blau | |||||
hex | 98 | 5A | F4 | 985AF4 | |||
hex | R x 1.00.00 | + | G x 1.00 | + | B | ||
hex | 980000 | + |
5A00 | + | F4 | = | 985AF4 |
dez | 152 | 90 | 244 | 9984756 | |||
dez | R x 65536 | + | G x 256 | + | B | ||
dez | 9961472 | + | 23040 | + | 244 | = | 9984756 |
RGB besteht aus 3 Farbwerten für Rot Grün und Blau mit jeweils einem Wert von 0 bis 255. Diese Zahl ist die höchste zweistellige Zahl im Hexadezimalsystem FF.
Der Farbwert ist allerdings ein Wert, wobei in Hexadezimal die letzten beiden Stellen für Blau, die mittleren für Grün und die ersten beiden Stellen für Rot reserviert sind. Diesen uint Farbwert kann man als Hex-Wert aber auch als Dezimalwert darstellen. Ich hatte anfangs Probleme das zu verstehen, geholfen hat mir folgendes Beispiel.
Ein Beispiel:
Drei dreistellige Werte in einer Zahl dargestellt. Der mindere Wert1 bleibt wie er ist der zweite, wird mit 1000 multipliziert, wert3 wird mit 1 Mill multipliziert. Diese 3 Werte werden addiert.
Stellen wir uns vor wir hätten 2 Werte, die man in einer Zahl darstellen will. Die Werte sind jeweils eine dreistellige Zahl. So könnte man für einen der beiden Werte die Stellen von 0 bis 999 reservieren und für die zweite Zahl die tausender Stellen, also von 1000 bis 999000. Das gleiche kann man sich natürlich auch mit 3 oder mehr Zahlen vorstellen, indem man einfach nochmal die Zahlen von 1Mill bis 999 Millionen reserviert. Man könnte auch damit rechnen, indem man für einen Wert alles im Tausenderbereich rechnet. Dazu muss man den Wert einfach mit 1000 multiplizieren.
Auf diese Weise wird dieser Hexadezimale Farbwert erzeugt. Wenn man das in dezimal umrechnet, hat man die ersten 256 Werte für blau, das entspräche in meinem Beispiel den Stellen 0 bis 999, dann folgen die nächsten Stellen für grün. Allerdings kann man das im Dezimalsystem nicht so schön sehen, denn es geht ja bei 256 weiter und nicht bei der vierstelligen Zahl 1000. So hätte die Farbe Grün 00FF00 den Dezimalwert 65280 und die Farbe Rot FF0000 den Wert 16.711.680. Die Farbe Gelb FFFF00 könnt ihr ja nun selber ausrechnen, indem Ihr Rot und Grün addiert und Blau 0000FF ist sowieso klar, das ist natürlich 255.
Nun mal ein Rechenbeispiel. Die Farbe Grün=30 / Rot=0 / Blau=0 (001E00) möchte ich als Dezimalzahl haben. Grün liegt in der Mitte. Bei meinem ersten Beispiel musste ich die Zahl mit 1000 multiplizieren, hier muss ich die Zahl mit 256 multiplizieren. 30 x 256 = 7680. Das ist der Hexwert 1E00 und der Wert 30 ist der hexWert 1E. Man sieht es funktioniert.
Die erste fünfstellige Zahl in Hex (FFFF+1=10000) ist in Dez 65536. Also müssen wir, um den Rotwert zu erhalten, ihn mit dieser Zahl multiplizieren. In Dez ist 30 x 65536 = 1966080 das ist in Hex 1E0000.
Ich hoffe das ist einigermaßen anschaulich erklärt.
Wie kann man mit diesen Hexwerten rechnen?
Im Dezimalsystem habe ich 10 Zeichen von 0 bis 9. Im Dezimalsystem mulitpliziere ich mit 10, um die Zahl zu erhalten, die eine Stelle mehr hat. 1x10=10, 10x10=100 etc.
Im Hexsystem habe ich 16 Zeichen, von 0-F. Da mulitipliziere ich mit 16 um die Zahl zu erhalten die eine Stelle mehr hat. Allerdings müsste es korrekterweise heißen ich mulitpliziere mit der 10 des Hexsystems, welche der 16 im Dezimalsystems entspricht. Dann erhalte ich folgende Zahlen.
Dez | Hex | Bin | ||
1 | x 16 = | 16 | 10 | 1.0000 |
16 | x 16 = | 256 | 1 00 | 1.0000.0000 |
256 | x 16 = | 4.096 | 10 00 | 1.0000.0000.0000 |
4096 | x 16 = | 65.536 | 1 00 00 | 1.0000.0000.0000.0000 |
65536 | x 16 = | 1.048.576 | 10 00 00 | 1.000.0000.0000.0000.0000 |
1048576 | x 16 = | 16.777.216 | 1 00 00 00 | 1.000.0000.0000.0000.0000.00000 |
Die Grafikkarte zerlegt die ersten 24 Bit einer Speicherstelle in drei 8ter Gruppen (=Bytes). Das minderwertige Byte für Blau etc.
Das ist unübersichtilich. Man unterteilt für die menschliche Lesbarkeit nochmal jede Farbe in 4er Gruppen und schreibt diese als Hexwerte.
Rot | Grün | Blau | |
bin | 0000.0000 | 0000.0000 | 0000.0000 |
hex | 00 | 00 | 00 |
dez | 1.048.576 | 65536 | 4096 | 256 | 16 | 1 |
Dezimalwert in Hex mit folgender Funktion
meineZahl.toString(16)
Für diese Verschiebungen gibt es in Actionscript und vielen anderen Programmiersprachen Operatoren.
9 * 256 entspricht 9 << 8 Verschiebung um 8 Stellen in Bit und um 2 Stellen in Hex
in Hex entspricht das obige Beispiel 900. Im Dezimalsystem ist es 2304. Eine eher nichtssagende Zahl.
Es gibt auch einen Operator um nach rechts zu verschieben.
2304 >> 8 entspricht somit der Zahl 9 in Hex und Dezimalsystem. Es enstpricht 2304 / 256
x << 16 verschiebt 4 Stellen in Hex nach links und 16 Stellen in Bit. Es entspricht einer Multiplikation mit 65536 (siehe oben).
Mit dieser Verschiebung ist es möglich einen Farbwert folgendermaßen zu definieren.
Es entspricht dem Hex-Wert FFFF00
var color:uint = 255 << 16 | 255 << 8 | 0;
Die Schreibweise entspricht
var color:uint = (255 << 16) + (255 << 8) + 0;
Mit diesen Verschiebungen kann man aus einem Farbwert die Farben R, G und B folgendermaßen berechnen.
var col:uint = 0x99CC00;
trace(col); //10079232
trace(col.toString(16)); //99CC00
var rot:uint = col >> 16;
trace(rot.toString(16));//99
var gruen:uint = (col >> 8) - (rot << 8);
trace(gruen.toString(16));//cc
var blau:uint = col - (rot << 16) - (gruen << 8);
trace(blau.toString(16));//0
Erklärung:
Die Farbe rot lässt sich sehr einfach freistellen, indem man sie Bitweise um 16 Stellen nach rechts verschiebt, was im Hex System einer Verschiebung von 4 Stellen entspricht.
Die Farbe grün benötigt 2 Rechenschritte. Eine Verschiebung nach rechts um 2 Stellen im Hex-System. Dann erhält man in diesem Beispiel die Hex Zahl 99CC. Davon muss man nun die Hexzahl 9900 abziehen. Diese Zahl erhält man, indem man den zuvor erzeugten Rot-Wert um 2 Stellen (Hex) nach Links verschiebt. rot << 8 macht aus der Hex-Zahl 99 die Hex-Zahl 9900.
Die Zahl blau wird auf ähnliche Weise erzeugt. Man verschiebt die zuvor erzeugten Farben rot und gruen nach links auf die entsprechende Stelle und zieht beide Werte von der Gesamtfarbe ab.
Möglich ist auch diese einfachere Schreibweise:
var col:uint = 0x99CC00;
var newR: Number = ((col >> 16) & 0xFF);
var newG: Number = ((col >> 8) & 0xFF);
var newB: Number = (col & 0xFF);
Über die Eigenschaft color legt man einen Farbwert fest und kann dann ein Objekt mittels transform einfärben. Im folgenden Beispiel kann der unveränderte MC jede beliebige Farbigkeit haben, er wird dann komplett eingefärbt.
Auch in diesem Beispiel geht es darum einen MC einzufärben. Hier wird eine Transformation einer bestehenden Farbe auf ein Zufallsfarbe hin animiert. Sobald die Zufallsfarbe erreicht ist, wird eine neue Zufallsfarbe erzeugt.
Beachten Sie bei der Programmierung die bitweise Verschiebung, mit der es sehr einfach ist, einen gültigen Farbwert aus den 3 Werten von Rot Grün und Blau zu erzeugen.
var color:uint = r << 16 | g << 8 | b;
In der Flashdatei muss ein Movieclip mit Export für Actionscript vorhanden sein, der den Klassennamen Quader hat.
var r:Number = 0; var g:Number = 0; var b:Number = 0; var rDest:Number; var gDest:Number; var bDest:Number; // die Zielfarben bekommen Zufallswerte zugewiesen resetColors(); var colT:ColorTransform=new ColorTransform(); var mc:Quader = new Quader(); mc.x = 100; mc.y = 100; addChild(mc); mc.addEventListener(Event.ENTER_FRAME, changeColors); function changeColors(evt:Event):void { r -= (r - rDest) * .02; g -= (g - gDest) * .02; b -= (b - bDest) * .02; var color:uint = r << 16 | g << 8 | b;; colT.color = color; evt.currentTarget.transform.colorTransform = colT; // wenn Farbe erreicht wird erstelle eine neue Farbe if ( Math.abs( r - rDest) < 1 && Math.abs( g - gDest) < 1 && Math.abs( b - bDest) ) { resetColors(); } } function resetColors():void { rDest = Math.random() * 255; gDest = Math.random() * 255; bDest = Math.random() * 255; }
Nicht immer möchte man ein Objekt komplett einfärben, sondern stattdessen die ursprünglichen Farben transformieren.
Das ColorTransform Objekt hat 8 Parameter, die ersten 4 sind Mulitplier, für rot, grün, blau und alpha (Transparenz).
Das heißt die vorhandenen Farbwerte, werden mit dem Multiplier multipliziert. Der Standardwert 1, verändert den vorhandenen Wert nicht.
Die letzten 4 Parameter sind Offset Werte für die 3 Farben rot, grün, blau und alpha. Der Offset Wert wird zu dem vorhandenen Farbwert, der mit dem Multiplier multipliziert wurde, hinzuaddiert. Die Werte reichen von -255 bis 255. Ein Wert der darüber geht, wird auf 255 gesetzt. Ein Wert unter 0 wird auf 0 gesetzt.
Die Parameter lassen sich auch über Eigenschaften definieren.
redMultiplier, greenMultiplier, blueMultiplier, alphaMultiplier
redOffset, greenOffset, blueOffset, alphaOffset
ColorTransform(redMultiplier:Number = 1.0, greenMultiplier:Number = 1.0, blueMultiplier:Number = 1.0, alphaMultiplier:Number = 1.0, redOffset:Number = 0, greenOffset:Number = 0, blueOffset:Number = 0, alphaOffset:Number = 0)
Beispiel 1
Ein Beispiel: Ich habe einen einfarbigen MC, Instanzname myMc und möchte den vorhandenen Rotwert der Farbe durch 120 ersetzen und den vorhandenen Blauwert auf die Hälfte reduzieren. Der Grünwert soll erhalten bleiben.
var colT:ColorTransform = new ColorTransform();
colT.redMultiplier = 0;
colT.redOffset = 120;
colT.blueMultiplier = 0.5;
myMc.transform.colorTransform = colT;
Beispiel 2
Will man die RGB Wert komplett neu bestimmen, könnte man alle 3 Farbwerte mit 0 Multiplizieren und die neuen Werte als Offset eingeben.
Beispiel 3
Ich habe einen weißen MC mit schwarzer Outline und möchte die Farbe weiß durch eine Farbe ersetzen die Outline soll schwarz bleiben. Siehe folgendendes Beispiel
Hier werden die Farben über eine Slider Komponente interaktiv definiert. Beachte, dass auch hier der ursprüngliche Movieclip eine weiße Füllfarbe haben muss.
import fl.events.SliderEvent; //------------------------------------------------------ var r:uint=0; var g:uint=0; var b:uint=0; var newR:Number=1/255*r; var newG:Number=1/255*g; var newB:Number=1/255*b; var hue:Number; var saturation:Number; var brightness:Number; var farbTransform:ColorTransform = new ColorTransform(); //------------------------------------------------------ function init():void { rAnzeige.text=String(r); gAnzeige.text=String(g); bAnzeige.text=String(b); farbTransform.redMultiplier=newR; farbTransform.greenMultiplier=newG; farbTransform.blueMultiplier=newB; rechteck_mc.transform.colorTransform=farbTransform; } //------------------------------------------------------ function changeRed(event:SliderEvent):void { r=event.currentTarget.value; newR=1/255*r; rAnzeige.text=String(event.currentTarget.value); farbTransform.redMultiplier=newR; rechteck_mc.transform.colorTransform=farbTransform; } //------------------------------------------------------ function changeGreen(event:SliderEvent):void { g=event.currentTarget.value; newG=1/255*g; gAnzeige.text=String(event.currentTarget.value); farbTransform.greenMultiplier=newG; rechteck_mc.transform.colorTransform=farbTransform; } function changeBlue(event:SliderEvent):void { b=event.currentTarget.value; newB=1/255*b; bAnzeige.text=String(event.currentTarget.value); farbTransform.blueMultiplier=newB; rechteck_mc.transform.colorTransform=farbTransform; } //------------------------------------------------------ rSlider.addEventListener(SliderEvent.CHANGE, changeRed); gSlider.addEventListener(SliderEvent.CHANGE, changeGreen); bSlider.addEventListener(SliderEvent.CHANGE, changeBlue); //------------------------------------------------------ init();
Aus dem RGB Farbwert wird ein Helligkeitswert für ein Schwarzweißbild errechnet. Als Parameter wird ein Hexwert erwartet.
function colToBW(val) { var col:Array = new Array(); var red:uint; var green:uint; var blue:uint; var val:uint; var brightness:uint; col.red = (val >> 16) & 0xFF; col.green = (val >> 8) & 0xFF; col.blue = val & 0xFF; brightness=(col.red + uint(col.green) + uint(col.blue))/3; return brightness; } var bw:uint = colToBW(0xFFFF00); trace(bw);
In dieser Funktion wird ein Hexwert erwartet. Es werden die Werte für Rot, Grün und Blau als Dezimalzahlen zurückgegeben.
function hexToRGB(val) { var col:Array = new Array(); var red:uint; var green:uint; var blue:uint; var val:uint; col.red = (val >> 16) & 0xFF; col.green = (val >> 8) & 0xFF; col.blue = val & 0xFF; return col; } var rgb:Array = hexToRGB(0xFFFF00); trace(rgb.red); trace(rgb.green); trace(rgb.blue);
Füllungen mit Farbverläufen definieren. Siehe auch drawRect bei Adobe und meinen Tipp Grafiken zeichnen
Mit dem ColorMatrix Filter kann man Farben gezielt verändern. Mit der AdjustColor Klasse hat man sogar die Möglichkeit die Farben nach dem HSB Prinzip in Flash zu verändern. Viele kennen wahrscheinlich die Funktion Farbton/ Sättigung aus Photoshop oder anderen Programmen, wo man die Möglichkeit hat die Farbton-, Sättigung- und/oder Helligkeitswerte eines Bildes zu verändern. Diese Möglichkeiten zusammen mit der Kontrastregelung hat man nun auch in AS3 mit AdjustColor. Siehe dazu die Adobe Referenzen
Die Werte reichen bei Farbton von -180 bis +180 bei den anderen drei Parametern von -100 bis +100. Man muss alle 4 Parameter definieren, sonst funktioniert es nicht.
Im folgenden Beispiel wird ein Bild folgendermaßen verändert:
Normal / Farbton / Sättigung / Helligkeit / Kontrast
package { import flash.display.DisplayObject; import flash.display.Loader; import flash.display.Sprite; import flash.events.Event; import flash.events.IOErrorEvent; import flash.filters.ColorMatrixFilter; import flash.net.URLRequest; import fl.motion.AdjustColor; public class ColorMatrixFilterExample extends Sprite { private var size:uint=150; private var url:String="Image.jpg"; public function ColorMatrixFilterExample() { buildChild(null); buildChild(applyHue); buildChild(applySaturation); buildChild(applyBrightness); buildChild(applyContrast); } private function buildChild(loadHandler:Function):void { var loader:Loader = new Loader(); loader.x=numChildren*size; loader.y=10; loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler); if (loadHandler!=null) { loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadHandler); } var request:URLRequest=new URLRequest(url); loader.load(request); addChild(loader); } private function applyContrast(event:Event):void { var child:DisplayObject=DisplayObject(event.target.loader); var adCol:AdjustColor = new AdjustColor(); adCol.hue=0;//-180 und 180; adCol.brightness=0;//-100 100; adCol.contrast=100;//-100 100 adCol.saturation=0;//Saturation-100 und 100 var matrix:Array=adCol.CalculateFinalFlatArray(); applyFilter(child, matrix); } private function applyHue(event:Event):void { var child:DisplayObject=DisplayObject(event.target.loader); var adCol:AdjustColor = new AdjustColor(); adCol.hue=150;//-180 und 180; adCol.brightness=0;//-100 100; adCol.contrast=0;//-100 100 adCol.saturation=0;//Saturation-100 und 100 var matrix:Array=adCol.CalculateFinalFlatArray(); applyFilter(child, matrix); } private function applyBrightness(event:Event):void { var child:DisplayObject=DisplayObject(event.target.loader); var adCol:AdjustColor = new AdjustColor(); adCol.hue=0;//-180 und 180; adCol.brightness=50;//-100 100; adCol.contrast=0;//-100 100 adCol.saturation=0;//Saturation-100 und 100 var matrix:Array=adCol.CalculateFinalFlatArray(); applyFilter(child, matrix); } private function applySaturation(event:Event):void { var child:DisplayObject=DisplayObject(event.target.loader); var adCol:AdjustColor = new AdjustColor(); adCol.hue=0;//-180 und 180; adCol.brightness=0;//-100 100; adCol.contrast=0;//-100 100 adCol.saturation=100;//Saturation-100 und 100 var matrix:Array=adCol.CalculateFinalFlatArray(); applyFilter(child, matrix); } private function applyFilter(child:DisplayObject, matrix:Array):void { var filter:ColorMatrixFilter=new ColorMatrixFilter(matrix); var filterAr:Array = new Array(); filterAr.push(filter); child.filters=filterAr; } private function ioErrorHandler(event:IOErrorEvent):void { trace("Unable to load image: " + url); } } }
import fl.motion.AdjustColor; var adCol:AdjustColor = new AdjustColor(); this.stage.addEventListener(MouseEvent.CLICK, applyHue); function applyHue(event:MouseEvent):void { adCol.hue=50;//-180 und 180; adCol.brightness = 0;//-100 100; adCol.contrast = 0;//-100 100 adCol.saturation = 0;//Saturation-100 und 100 var matrix:Array = adCol.CalculateFinalFlatArray(); applyFilter(my_mc, matrix); } function applyFilter(child:DisplayObject, matrix:Array):void { var filter:ColorMatrixFilter = new ColorMatrixFilter(matrix); var filterAr:Array = new Array(); filterAr.push(filter); child.filters = filterAr; }
Auf der Suche nach einer Color Picker Komponente zum freien download habe ich immer wieder die Color Picker gefunden, die aus einem Bild ein BitmapData Objekt erzeugen und daraus dann mit getPixel die Farbwerte herauslesen. Wie das geht seht ihr in meinem Tipp BitmapData Leider erfüllen die Bilder die dort benutzt werden nicht meine Ansrpüche, denn gerade Pastelltöne, also die Farben die nahe einem Grauwert liegen, kann man aus den Farbbildern nicht herausholen. Daher habe ich mir eine Lösung gebastelt, wo ich die Sättigung der Farbe mittels Sliderkomponente einstellen kann. Die Farben werden auch nicht aus einem Jpg geholt sondern in Flash mittels setPixel in ein BitmapData Objekt gesetzt. Dadurch erhält man alle Farben, die es so gibt im Farbsystem. Einen großen Teil des Codes habe ich von Zevan bei Actionsnippets übernommen, vielen Dank dafür.
Erstellt und importiert meine ColorPick.as. Es befindet sich ein dynamisches Textfeld names "anzeige" auf der Bühne, um die Funktionsweise des EventDispatcher zu demonstrieren. Über die Variable rgb kann man auf die ausgewählte Farbe zugreifen.
package { import flash.display.MovieClip; import flash.display.Sprite; import flash.events.*; import flash.display.BitmapData; import flash.display.Bitmap; import flash.display.GradientType; import flash.display.SpreadMethod; import flash.geom.ColorTransform; import flash.text.TextField; import flash.text.TextFormat; import flash.text.TextFieldAutoSize; import flash.text.AntiAliasType; import flash.text.TextFormatAlign; import flash.geom.Rectangle; import flash.geom.Matrix; // hsv to rgb ported from here: //http://www.cs.rit.edu/~ncs/color/t_convert.html //http://actionsnippet.com/?p=1627 public class ColorPick extends MovieClip { public var rgb:uint; private var b1:Sprite; private var butCol:Sprite; private var slideCol:Sprite= new Sprite(); private var canvas:BitmapData; private var colorField:Bitmap; private var sld:Sprite= new Sprite(); private var dreieck:Sprite= new Sprite(); private var draggin:Boolean=false; private var slideHeight:Number=158; private var colorRect:Sprite = new Sprite(); private var colorRect2:Sprite = new Sprite(); private var container:Sprite = new Sprite(); private var einfaerben:ColorTransform=new ColorTransform(); protected var format:TextFormat; private var textfeld1:TextField; private var textfeld2:TextField; public static const COLOR_CLICK:String="ColorPickEvent_COLOR_CLICK"; public function ColorPick( _rgb:uint=0xFF6600):void { rgb=_rgb; if (stage) { init(); } else { addEventListener(Event.ADDED_TO_STAGE,init); } } private function init(e:Event=null):void { canvas=new BitmapData(360,200,false,0x000000); colorField=new Bitmap(canvas); colorField.x=10; colorField.y=10; container.addChild(colorField); setSaturation(1); drawContent(); removeEventListener(Event.ADDED_TO_STAGE, init); addEventListener(Event.REMOVED_FROM_STAGE, destroy); b1.addEventListener(MouseEvent.CLICK,buttonClick); dreieck.addEventListener(MouseEvent.MOUSE_DOWN, startSlide); stage.addEventListener(MouseEvent.MOUSE_UP, stopSlide); addEventListener(MouseEvent.MOUSE_MOVE, changeValue); addEventListener(MouseEvent.MOUSE_MOVE, setColor); addEventListener(MouseEvent.MOUSE_DOWN, setColor2); addEventListener(MouseEvent.ROLL_OUT, closeColor); } private function hsv(h:Number, s:Number, v:Number):Array { var r:Number,g:Number,b:Number; var i:int; var f:Number,p:Number,q:Number,t:Number; if (s==0) { r=g=b=v; return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; } h/=60; i=Math.floor(h); f=h-i; p = v * (1 - s); q = v * (1 - s * f); t = v * (1 - s * (1 - f)); switch ( i ) { case 0 : r=v; g=t; b=p; break; case 1 : r=q; g=v; b=p; break; case 2 : r=p; g=v; b=t; break; case 3 : r=p; g=q; b=v; break; case 4 : r=t; g=p; b=v; break; default :// case 5: r=v; g=p; b=q; break; } return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; } private function setSaturation(val:Number):void { canvas.lock(); var size:int=canvas.width*canvas.height; var xp:int,yp:int,c:Array,i:int; for (i = 0; i < size; i++) { xp=i%360; yp=i/360; c=hsv(xp,val,yp/canvas.height); canvas.setPixel(xp, yp, c[0] <<16 | c[1] <<8 | c[2]); } canvas.unlock(); } private function startSlide(evt:MouseEvent):void { draggin=true; var rect:Rectangle=new Rectangle(0,0,0,slideHeight); dreieck.startDrag(true, rect); } private function stopSlide(evt:MouseEvent):void { if (draggin) { dreieck.stopDrag(); } draggin=false; } private function changeValue(event:MouseEvent):void { setSaturation(dreieck.y/slideHeight); } private function showColor():void { if (colorField.mouseX < canvas.width&&colorField.mouseY < canvas.height) { rgb=canvas.getPixel(colorField.mouseX,colorField.mouseY); einfaerben.color=rgb; } } private function setColor(evt:MouseEvent):void { showColor(); textfeld1.text=rgb.toString(16); colorRect.transform.colorTransform=einfaerben; } private function setColor2(evt:MouseEvent):void { if (colorField.mouseX < canvas.width&&colorField.mouseY < canvas.height) { showColor(); textfeld2.text=rgb.toString(16); colorRect2.transform.colorTransform=einfaerben; butCol.transform.colorTransform=einfaerben; einfaerben.color=hex2Hue(rgb); slideCol.transform.colorTransform=einfaerben; dispatchEvent(new Event(COLOR_CLICK)); } } private function drawContent():void { var xpos:Number=390; var ypos:Number=52; sld.x=slideCol.x=xpos; sld.y=slideCol.y=ypos; container.addChild(slideCol); container.addChild(sld); //Dreieck, Anfasser für Slider sld.addChild(dreieck); dreieck.x=0; dreieck.y=slideHeight; dreieck.graphics.beginFill(0x000000); dreieck.graphics.lineTo(0,0); dreieck.graphics.lineTo(15,-8.75); dreieck.graphics.lineTo(15,8.75); dreieck.graphics.endFill(); // Sensorpunkt Kreis unsichtbar dreieck.graphics.beginFill(0x000000, 0); dreieck.graphics.drawCircle(9, 0, 16); //Rechteck zeichnen var colors:Array=[0x707070,0x000000]; var alphas:Array=[1,0]; var ratios:Array=[0,250]; var matr:Matrix = new Matrix(); matr.createGradientBox(slideHeight, slideHeight); matr.rotate(Math.PI/2); var spreadMethod:String=SpreadMethod.REFLECT; //this.graphics.beginFill(0xFFaa45); sld.graphics.beginGradientFill(GradientType.LINEAR,colors, alphas, ratios,matr, spreadMethod); sld.graphics.drawRect(-10, 0, 10, slideHeight); sld.graphics.endFill(); slideCol.graphics.beginFill(rgb); slideCol.graphics.drawRect(-10, 0, 10, slideHeight); slideCol.graphics.endFill(); container.addChild(sld); colorRect.graphics.beginFill(rgb); colorRect.graphics.drawRect(0, 0, 100, 30); colorRect.graphics.endFill(); colorRect2.graphics.beginFill(rgb); colorRect2.graphics.drawRect(0, 0, 100, 30); colorRect2.graphics.endFill(); format= new TextFormat(); format.size=18; format.font="Arial"; textfeld1 = new TextField(); textfeld2 = new TextField(); textfeld1.defaultTextFormat=format; textfeld1.autoSize=TextFieldAutoSize.LEFT; textfeld1.antiAliasType=AntiAliasType.ADVANCED; textfeld1.selectable=false; textfeld1.mouseEnabled=true; textfeld1.text=rgb.toString(16); textfeld2.defaultTextFormat=format; textfeld2.autoSize=TextFieldAutoSize.LEFT; textfeld2.antiAliasType=AntiAliasType.ADVANCED; textfeld2.selectable=true; textfeld2.mouseEnabled=true; textfeld2.text=rgb.toString(16); colorRect.x=10; colorRect.y=215; textfeld1.x=115; textfeld1.y=215; textfeld2.x=295; textfeld2.y=215; colorRect2.x=190; colorRect2.y=215; container.addChild(textfeld1); container.addChild(textfeld2); container.addChild(colorRect); container.addChild(colorRect2); container.graphics.lineStyle(1, 0x333333, .75); container.graphics.beginFill(0xffffff); container.graphics.drawRect(0, 0, 430, 255); container.graphics.endFill(); addChild(container); container.visible=false; b1 = new Sprite(); b1.graphics.lineStyle(1, 0x000000); b1.graphics.beginFill(0xffffff); b1.graphics.drawRect(0, 0, 30, 30); b1.graphics.endFill(); b1.buttonMode=true; b1.useHandCursor=true; butCol=new Sprite(); butCol.graphics.beginFill(rgb); butCol.graphics.drawRect(0, 0, 22, 22); butCol.graphics.endFill(); butCol.x=4; butCol.y=4; b1.x=380; b1.y=10; b1.addChild(butCol); addChild(b1); } private function buttonClick(e:MouseEvent) { if (container.visible) { container.visible=false; } else { container.visible=true; } } private function closeColor(e:MouseEvent) { container.visible=false; } private function destroy(e:Event):void { removeEventListener(Event.REMOVED_FROM_STAGE, destroy); b1.removeEventListener(MouseEvent.CLICK,buttonClick); dreieck.removeEventListener(MouseEvent.MOUSE_DOWN, startSlide); stage.removeEventListener(MouseEvent.MOUSE_UP, stopSlide); removeEventListener(MouseEvent.MOUSE_MOVE, changeValue); removeEventListener(MouseEvent.MOUSE_MOVE, setColor); removeEventListener(MouseEvent.MOUSE_DOWN, setColor2); removeEventListener(MouseEvent.ROLL_OUT, closeColor); } private function hex2Hue(color:uint):uint { var ar1:Array=hex2hsb(color); ar1[1]=100; ar1[2]=100; return hsb2hex(ar1); } private function hex2rgb(hex:uint):Array { var rgb:Array = new Array(); rgb[0]=hex>>16; rgb[1]=hex>>8&0xFF; rgb[2]=hex&0xFF; return rgb; } private function rgb2hex(rgb:Array):uint { var hex=rgb[0]<<16^rgb[1]<<8^rgb[2]; return hex; } private function hsb2rgb(hsb:Array):Array { var red,grn,blu,i,f,p,q,t; hsb[0]%=360; if (hsb[2]==0) { return (new Array(0,0,0)); } hsb[1]/=100; hsb[2]/=100; hsb[0]/=60; i=Math.floor(hsb[0]); f=hsb[0]-i; p = hsb[2]*(1-hsb[1]); q = hsb[2]*(1-(hsb[1]*f)); t = hsb[2]*(1-(hsb[1]*(1-f))); if (i==0) { red=hsb[2]; grn=t; blu=p; } else if (i==1) { red=q; grn=hsb[2]; blu=p; } else if (i==2) { red=p; grn=hsb[2]; blu=t; } else if (i==3) { red=p; grn=q; blu=hsb[2]; } else if (i==4) { red=t; grn=p; blu=hsb[2]; } else if (i==5) { red=hsb[2]; grn=p; blu=q; } red=Math.floor(red*255); grn=Math.floor(grn*255); blu=Math.floor(blu*255); return (new Array(red,grn,blu)); } private function rgb2hsb(rgb:Array):Array { var x,f,i,hue,sat,val; rgb[0]/=255; rgb[1]/=255; rgb[2]/=255; x=Math.min(Math.min(rgb[0],rgb[1]),rgb[2]); val=Math.max(Math.max(rgb[0],rgb[1]),rgb[2]); if (x==val) { return (new Array(undefined,0,val*100)); } f = (rgb[0] == x) ? rgb[1]-rgb[2] : ((rgb[1] == x) ? rgb[2]-rgb[0] : rgb[0]-rgb[1]); i = (rgb[0] == x) ? 3 : ((rgb[1] == x) ? 5 : 1); hue = Math.floor((i-f/(val-x))*60)%360; sat = Math.floor(((val-x)/val)*100); val=Math.floor(val*100); return (new Array(hue,sat,val)); } private function hsb2hex(hsb:Array):uint { var rgb=hsb2rgb(hsb); return (rgb2hex(rgb)); } private function hex2hsb(hex:uint):Array { var rgb=hex2rgb(hex); return (rgb2hsb(rgb)); } } }
Action in der fla
var myCol:ColorPick= new ColorPick(0x76b100); myCol.x=20; myCol.y=20; addChild(myCol); myCol.addEventListener(ColorPick.COLOR_CLICK, showText); function showText(evt:Event):void { trace(myCol.rgb); anzeige.text=myCol.rgb.toString(16); }
Ich habe hier eine Klassendatei erstellt, die sehr viele Umrechnungen von Farben enthält. Einen großen Teil der Methoden habe ich von http://snipplr.com
Einige Methoden habe ich etwas erweitert oder umgeschrieben.
package { public class PPColor { /* copyright: most of the scripts are from http://snipplr.com especially the author @author Rivaledsouls I have changed some code http://www.pastorpixel.de feel free to use if you dont delete the coypright info rgb2uint erwartet, die 3 Farbwerte rot, grün, blau jeweils von 0-255 es wird ein gültiger Farbwert hex(uint) ausgegeben hsb2uint erwartet die 3 Farbwerte H=Farbton 0-360, S=Sättigung 0-100, B=Brightness 0-100 es wird ein gültiger Farbwert hex(uint) ausgegeben rgb2hsb erwartet werden die 3 Farbwerte für rot grün blau von jeweils 0-255 zurückgegben wird ein Objekt mit den Parametern h, s, b für Hue/Farbton, Saturation, Brightness siehe Beispiel var col:Object = PPColor.rgb2hsb(255, 0, 0); trace(col.h); //255 trace(col.s); //0 trace(col.b); //255 hex2rgb es wird ein gültiger Farbwert erwartet, es wird ein Object zurückgegeben, mit den Variablen r, g, b für die 3 RGB Farbwerte siehe Beispiel var col:Object = PPColor.hex2rgb(0xFF00FF); trace(col.r); //255 trace(col.g); //0 trace(col.b); //255 uint2hex es wird ein uint Farbwert erwartet und ein hex String zurückgegeben das Schema ist 0x002200 */ public function PPColor() { // constructor code } public static function rgb2uint(r:int, g:int, b:int):uint { var hex:uint = r << 16 | g << 8 | b; return hex; } public static function hsb2uint(h:int, s:int, b:int):uint { // var rgb:Object = new Object(); var max:Number = (b * 0.01) * 255; var min:Number = max * (1 - (s * 0.01)); if (h == 360) { h = 0; } if (s == 0) { rgb.r = rgb.g = rgb.b = b * (255 * 0.01); } else { var _h:Number = Math.floor(h / 60); switch (_h) { case 0 : rgb.r = max; rgb.g = min + h * (max - min) / 60; rgb.b = min; break; case 1 : rgb.r = max - (h - 60) * (max - min) / 60; rgb.g = max; rgb.b = min; break; case 2 : rgb.r = min; rgb.g = max; rgb.b = min + (h - 120) * (max - min) / 60; break; case 3 : rgb.r = min; rgb.g = max - (h - 180) * (max - min) / 60; rgb.b = max; break; case 4 : rgb.r = min + (h - 240) * (max - min) / 60; rgb.g = min; rgb.b = max; break; case 5 : rgb.r = max; rgb.g = min; rgb.b = max - (h - 300) * (max - min) / 60; break; case 6 : rgb.r = max; rgb.g = min + h * (max - min) / 60; rgb.b = min; break; } rgb.r = Math.min(255,Math.max(0,Math.round(rgb.r))); rgb.g = Math.min(255,Math.max(0,Math.round(rgb.g))); rgb.b = Math.min(255,Math.max(0,Math.round(rgb.b))); } return rgb2uint(rgb.r, rgb.g, rgb.b);// return rgb; } /* var col:Object = PPColor.rgb2hsb(255, 0, 0); trace(col.h); //255 trace(col.s); //0 trace(col.b); //255 */ public static function rgb2hsb(r:int, g:int, b:int):Object { var hsb:Object = new Object ; var _max:Number = Math.max(r,g,b); var _min:Number = Math.min(r,g,b); hsb.s = (_max != 0) ? (_max - _min) / _max * 100:0; hsb.b = _max / 255 * 100; if (hsb.s == 0) { hsb.h = 0; } else { switch (_max) { case r : hsb.h = (g - b) / (_max - _min) * 60 + 0; break; case g : hsb.h = (b - r) / (_max - _min) * 60 + 120; break; case b : hsb.h = (r - g) / (_max - _min) * 60 + 240; break; } } hsb.h = Math.min(360,Math.max(0,Math.round(hsb.h))); hsb.s = Math.min(100,Math.max(0,Math.round(hsb.s))); hsb.b = Math.min(100, Math.max(0, Math.round(hsb.b))); return hsb; } /* var col:Object = PPColor.hex2rgb(0xFF00FF); trace(col.r); //255 trace(col.g); //0 trace(col.b); //255 */ public static function uint2hsb(val:uint):Object { var col:Object = PPColor.hex2rgb(val); var hsb:Object = PPColor.rgb2hsb(col.r, col.g, col.b); return hsb; } public static function hex2rgb(value:uint):Object { var rgb:Object = new Object(); rgb.r = (value >> 16) & 0xFF; rgb.g = (value >> 8) & 0xFF; rgb.b = value & 0xFF; return rgb; } public static function hex2css(color:int):String { return "#" + color.toString(16).toUpperCase(); } public static function uint2hex(dec:uint):String { var hex:String = dec.toString(16); var zero:String = ""; var i:uint = 0; while (i < 6) { if (i >= 6 - hex.length) { break; } zero = zero + "0"; i++; } hex = "0x" + zero + hex; return hex; } } }Im folgenden Beispiel habe ich mit der oben aufgeführten PPColor Klasse einen Colorpicker erstellt. Das eigentliche Farbfeld besteht aus mehreren MCs die übereinanderliegen und Farben mit Verläufen und Transparenzen haben. Es gibt einige Sliderkomponenten Textfelder etc.
import fl.events.SliderEvent; var hue:uint = 0; var sat:uint = 100; var bri:uint = 100; var colT:ColorTransform=new ColorTransform(); function changeColor():void { colT.color=PPColor.hsb2uint(hue,100,100) farbMc.transform.colorTransform = colT; colT.color = PPColor.hsb2uint(hue,sat,bri); mc.transform.colorTransform = colT; tFarbe.text=PPColor.uint2hex(colT.color); tHue.text=String(hue); tSat.text=String(sat); tBri.text=String(bri); } changeColor(); sldH.addEventListener(SliderEvent.CHANGE, setH); sldS.addEventListener(SliderEvent.CHANGE, setS); sldB.addEventListener(SliderEvent.CHANGE, setB); function setH(evt:SliderEvent):void { hue = evt.currentTarget.value; changeColor(); } function setS(evt:SliderEvent):void { sat = evt.currentTarget.value; changeColor(); } function setB(evt:SliderEvent):void { bri = evt.currentTarget.value; changeColor(); } farbfeld.addEventListener(MouseEvent.CLICK, setFarbe); function setFarbe(evt:MouseEvent):void { sat = Math.round((farbfeld.mouseX+100)/2); bri=100-Math.round((farbfeld.mouseY+100)/2); sldS.value = sat; sldB.value = bri; changeColor(); }
Startseite: www.pastorpixel.de