Xây dựng theo số this solution để giải quyết quy tắc của câu hỏi # 2, thuật toán sau hoán đổi màu xung quanh điểm giữa của pie. Hai thông số:
- pNbColors là số lát trong chiếc bánh
- pNonAdjacentSimilarColor một Boolean để chỉ ra nếu bạn muốn có màu sắc tương tự liền kề hay không.
Tôi đang sử dụng ColorHSL, ColorRGB và ColorUtils (được cung cấp dưới đây).
public static function ColorArrayGenerator(
pNbColors:int,
pNonAdjacentSimilarColor:Boolean = false):Array
{
var colors:Array = new Array();
var baseRGB:ColorRGB = new ColorRGB();
baseRGB.setRGBFromUint(0x8A56E2);
var baseHSL:ColorHSL = new ColorHSL();
rgbToHsl(baseHSL, baseRGB);
var currentHue:Number = baseHSL.Hue;
colors.push(baseRGB.getUintFromRGB());
var step:Number = (360.0/pNbColors);
var nextHSL:ColorHSL;
var nextRGB:ColorRGB;
var i:int;
for (i = 1; i < pNbColors; i++)
{
currentHue += step;
if (currentHue > 360)
{
currentHue -= 360;
}
nextHSL = new ColorHSL(currentHue, baseHSL.Saturation, aseHSL.Luminance);
nextRGB = new ColorRGB();
hslToRgb(nextRGB, nextHSL);
colors.push(nextRGB.getUintFromRGB());
}
if (pNonAdjacentSimilarColor == true &&
pNbColors > 2)
{
var holder:uint = 0;
var j:int;
for (i = 0, j = pNbColors/2; i < pNbColors/2; i += 2, j += 2)
{
holder = colors[i];
colors[i] = colors[j];
colors[j] = holder;
}
}
return colors;
}
này tạo ra đầu ra phía bên tay phải:
ColorHSL lớp:
final public class ColorHSL
{
private var _hue:Number; // 0.0 .. 359.99999
private var _sat:Number; // 0.0 .. 100.0
private var _lum:Number; // 0.0 .. 100.0
public function ColorHSL(
hue:Number = 0,
sat:Number = 0,
lum:Number = 0)
{
_hue = hue;
_sat = sat;
_lum = lum;
}
[Bindable]public function get Hue():Number
{
return _hue;
}
public function set Hue(value:Number):void
{
if (value > 360)
{
_hue = value % 360;
} // remember, hue is modulo 360
else if (value < 0)
{
_hue = 0;
}
else
{
_hue = value;
}
}
[Bindable]public function get Saturation():Number
{
return _sat;
}
public function set Saturation(value:Number):void
{
if (value > 100.0)
{
_sat = 100.0;
}
else if (value < 0)
{
_sat = 0;
}
else
{
_sat = value;
}
}
[Bindable]public function get Luminance():Number
{
return _lum;
}
public function set Luminance(value:Number):void
{
if (value > 100.0)
{
_lum = 100.0;
}
else if (value < 0)
{
_lum = 0;
}
else
{
_lum = value;
}
}
}
ColorRGB lớp:
final public class ColorRGB
{
private var _red:uint;
private var _grn:uint;
private var _blu:uint;
private var _rgb:uint; // composite form: 0xRRGGBB or #RRGGBB
public function ColorRGB(red:uint = 0, grn:uint = 0, blu:uint = 0)
{
setRGB(red, grn, blu);
}
[Bindable]public function get red():uint
{
return _red;
}
public function set red(value:uint):void
{
_red = (value & 0xFF);
updateRGB();
}
[Bindable]public function get grn():uint
{
return _grn;
}
public function set grn(value:uint):void
{
_grn = (value & 0xFF);
updateRGB();
}
[Bindable]public function get blu():uint
{
return _blu;
}
public function set blu(value:uint):void
{
_blu = (value & 0xFF);
updateRGB();
}
[Bindable]public function get rgb():uint
{
return _rgb;
}
public function set rgb(value:uint):void
{
_rgb = value;
_red = (value >> 16) & 0xFF;
_grn = (value >> 8) & 0xFF;
_blu = value & 0xFF;
}
public function setRGB(red:uint, grn:uint, blu:uint):void
{
this.red = red;
this.grn = grn;
this.blu = blu;
}
public function setRGBFromUint(pValue:uint):void
{
setRGB(((pValue >> 16) & 0xFF), ((pValue >> 8) & 0xFF), (pValue & 0xFF));
}
public function getUintFromRGB():uint
{
return ((red << 16) | (grn << 8) | blu);
}
private function updateRGB():void
{
_rgb = (_red << 16) + (_grn << 8) + blu;
}
}
ColorUtils lớp:
final public class ColorUtils
{
public static function HSV2RGB(hue:Number, sat:Number, val:Number):uint
{
var red:Number = 0;
var grn:Number = 0;
var blu:Number = 0;
var i:Number;
var f:Number;
var p:Number;
var q:Number;
var t:Number;
hue%=360;
sat/=100;
val/=100;
hue/=60;
i = Math.floor(hue);
f = hue-i;
p = val*(1-sat);
q = val*(1-(sat*f));
t = val*(1-(sat*(1-f)));
if (i==0)
{
red=val;
grn=t;
blu=p;
}
else if (i==1)
{
red=q;
grn=val;
blu=p;
}
else if (i==2)
{
red=p;
grn=val;
blu=t;
}
else if (i==3)
{
red=p;
grn=q;
blu=val;
}
else if (i==4)
{
red=t;
grn=p;
blu=val;
}
else if (i==5)
{
red=val;
grn=p;
blu=q;
}
red = Math.floor(red*255);
grn = Math.floor(grn*255);
blu = Math.floor(blu*255);
return (red<<16) | (grn << 8) | (blu);
}
//
public static function RGB2HSV(pColor:uint):Object
{
var red:uint = (pColor >> 16) & 0xff;
var grn:uint = (pColor >> 8) & 0xff;
var blu:uint = pColor & 0xff;
var x:Number;
var val:Number;
var f:Number;
var i:Number;
var hue:Number;
var sat:Number;
red/=255;
grn/=255;
blu/=255;
x = Math.min(Math.min(red, grn), blu);
val = Math.max(Math.max(red, grn), blu);
if (x==val){
return({h:undefined, s:0, v:val*100});
}
f = (red == x) ? grn-blu : ((grn == x) ? blu-red : red-grn);
i = (red == x) ? 3 : ((grn == 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({h:hue, s:sat, v:val});
}
/**
* Generates an array of pNbColors colors (uint)
* The colors are generated to fill a pie chart (meaning that they circle back to the starting color)
* @param pNbColors The number of colors to generate (ex: Number of slices in the pie chart)
* @param pNonAdjacentSimilarColor Should the colors stay Adjacent or not ?
*/
public static function ColorArrayGenerator(
pNbColors:int,
pNonAdjacentSimilarColor:Boolean = false):Array
{
// Based on http://www.flexspectrum.com/?p=10
var colors:Array = [];
var baseRGB:ColorRGB = new ColorRGB();
baseRGB.setRGBFromUint(0x8A56E2);
var baseHSL:ColorHSL = new ColorHSL();
rgbToHsl(baseHSL, baseRGB);
var currentHue:Number = baseHSL.Hue;
colors.push(baseRGB.getUintFromRGB());
var step:Number = (360.0/pNbColors);
var nextHSL:ColorHSL;
var nextRGB:ColorRGB;
var i:int;
for (i = 1; i < pNbColors; i++)
{
currentHue += step;
if (currentHue > 360)
{
currentHue -= 360;
}
nextHSL = new ColorHSL(currentHue, baseHSL.Saturation, baseHSL.Luminance);
nextRGB = new ColorRGB();
hslToRgb(nextRGB, nextHSL);
colors.push(nextRGB.getUintFromRGB());
}
if (pNonAdjacentSimilarColor == true &&
pNbColors > 2)
{
var holder:uint = 0;
var j:int;
for (i = 0, j = pNbColors/2; i < pNbColors/2; i += 2, j += 2)
{
holder = colors[i];
colors[i] = colors[j];
colors[j] = holder;
}
}
return colors;
}
static public function rgbToHsl(hsl:ColorHSL, rgb:ColorRGB):void
{
var h:Number = 0;
var s:Number = 0;
var l:Number = 0;
// Normalizes incoming RGB values.
//
var dRed:Number = (Number)(rgb.red/255.0);
var dGrn:Number = (Number)(rgb.grn/255.0);
var dBlu:Number = (Number)(rgb.blu/255.0);
var dMax:Number = Math.max(dRed, Math.max(dGrn, dBlu));
var dMin:Number = Math.min(dRed, Math.min(dGrn, dBlu));
//-------------------------
// hue
//
if (dMax == dMin)
{
h = 0; // undefined
}
else if (dMax == dRed && dGrn >= dBlu)
{
h = 60.0 * (dGrn - dBlu)/(dMax - dMin);
}
else if (dMax == dRed && dGrn < dBlu)
{
h = 60.0 * (dGrn - dBlu)/(dMax - dMin) + 360.0;
}
else if (dMax == dGrn)
{
h = 60.0 * (dBlu - dRed)/(dMax-dMin) + 120.0;
}
else if (dMax == dBlu)
{
h = 60.0 * (dRed - dGrn)/(dMax - dMin) + 240.0;
}
//-------------------------
// luminance
//
l = (dMax + dMin)/2.0;
//-------------------------
// saturation
//
if (l == 0 || dMax == dMin)
{
s = 0;
}
else if (0 < l && l <= 0.5)
{
s = (dMax - dMin)/(dMax + dMin);
}
else if (l>0.5)
{
s = (dMax - dMin)/(2 - (dMax + dMin)); //(dMax-dMin > 0)?
}
hsl.Hue = h;
hsl.Luminance = l;
hsl.Saturation = s;
} // rgbToHsl
//---------------------------------------
// Convert the input RGB values to the corresponding HSL values.
//
static public function hslToRgb(rgb:ColorRGB, hsl:ColorHSL):void
{
if (hsl.Saturation == 0)
{
// Achromatic color case, luminance only.
//
var lumScaled:int = (int)(hsl.Luminance * 255.0);
rgb.setRGB(lumScaled, lumScaled, lumScaled);
return;
}
// Chromatic case...
//
var dQ:Number = (hsl.Luminance < 0.5) ? (hsl.Luminance * (1.0 + hsl.Saturation)): ((hsl.Luminance + hsl.Saturation) - (hsl.Luminance * hsl.Saturation));
var dP:Number = (2.0 * hsl.Luminance) - dQ;
var dHueAng:Number = hsl.Hue/360.0;
var dFactor:Number = 1.0/3.0;
var adT:Array = [];
adT[0] = dHueAng + dFactor; // Tr
adT[1] = dHueAng; // Tg
adT[2] = dHueAng - dFactor; // Tb
for (var i:int = 0; i < 3; i++)
{
if (adT[i] < 0)
{
adT[i] += 1.0;
}
if (adT[i] > 1)
{
adT[i] -= 1.0;
}
if ((adT[i] * 6) < 1)
{
adT[i] = dP + ((dQ - dP) * 6.0 * adT[i]);
}
else if ((adT[i] * 2.0) < 1) // (1.0/6.0) <= adT[i] && adT[i] < 0.5
{
adT[i] = dQ;
}
else if ((adT[i] * 3.0) < 2) // 0.5 <= adT[i] && adT[i] < (2.0/3.0)
{
adT[i] = dP + (dQ-dP) * ((2.0/3.0) - adT[i]) * 6.0;
}
else
{
adT[i] = dP;
}
}
rgb.setRGB(adT[0] * 255.0, adT[1] * 255.0, adT[2] * 255.0);
} // hslToRgb
//---------------------------------------
// Adjust the luminance value by the specified factor.
//
static public function adjustRgbLuminance(rgb:ColorRGB, factor:Number):void
{
var hsl:ColorHSL = new ColorHSL();
rgbToHsl(hsl, rgb);
hsl.Luminance *= factor;
if (hsl.Luminance < 0.0)
{
hsl.Luminance = 0.0;
}
if (hsl.Luminance > 1.0)
{
hsl.Luminance = 1.0;
}
hslToRgb(rgb, hsl);
}
//---------------------------------------
//
static public function uintTo2DigitHex(value:uint):String
{
var str:String = value.toString(16).toUpperCase();
if (1 == str.length)
{
str = "0" + str;
}
return str;
}
//---------------------------------------
//
static public function uintTo6DigitHex(value:uint):String
{
var str:String = value.toString(16).toUpperCase();
if (1 == str.length) {return "00000" + str;}
if (2 == str.length) {return "0000" + str;}
if (3 == str.length) {return "000" + str;}
if (4 == str.length) {return "00" + str;}
if (5 == str.length) {return "0" + str;}
return str;
}
}
thế nào là màu xanh giống như màu xanh lá cây? – peterchen
@peterchen - rất giống nếu bạn mù màu xanh lục;) – redcalx