我正在尝试在Flex 4中创建一个色轮组件,它允许我表示RGB和HSL数据。我这样做是用一个圆形的色轮代表我可以使用的各种色调,在中心的一个矩形渐变代表亮度和饱和度字段
目前我有所代表的对象,但我无法确定填充它们的最佳方法。我在中心方块创建必要的渐变没有问题,但我不能让外环构建一个-circular-gradient。看来flex中只有两个原生渐变是线性和径向的,但我需要渐变线性地跟随椭圆周围的路径。我怎么能做到这一点?
这是我迄今为止所做的尝试:
<s:Group>
<s:Ellipse x="7" y="7" width="136" height="136">
<s:stroke>
<s:LinearGradientStroke weight="14">
<s:GradientEntry ratio="0" color="0xFF0000"/>
<s:GradientEntry ratio="0.1647" color="0xFFFF00"/>
<s:GradientEntry ratio="0.3294" color="0x00FF00"/>
<s:GradientEntry ratio="0.4941" color="0x00FFFF"/>
<s:GradientEntry ratio="0.6588" color="0x0000FF"/>
<s:GradientEntry ratio="0.3529" color="0xFF00FF"/>
<s:GradientEntry ratio="1" color="0xFF0000"/>
</s:LinearGradientStroke>
</s:stroke>
</s:Ellipse>
<s:Rect x="32" y="32" width="86" height="86">
<s:fill>
<s:SolidColor/>
</s:fill>
</s:Rect>
</s:Group>
颜色及其比例从左到右正确定位我需要的渐变,但最终结果如下:
http://imageshack.us/photo/my-images/10/flexo.png/
我希望图像能够像这样出现:(来自paint shop pro 8的截图)
http://imageshack.us/photo/my-images/687/psph.png/
(对不起链接,但我还没有10个代表,所以我不能直接在帖子中发布图片)
(不,我还没有建立矩形渐变,因为它的颜色是基于外环...我还不担心矩形)
答案 0 :(得分:0)
我终于弄明白了
首先,我使用了本教程中提到的BoostWorthy.com的Ryan Taylor的代码: http://www.boostworthy.com/blog/?p=200
本教程的问题在于颜色范围不能获得我的色调色轮可用的所有色调,因为他使用正弦波来计算角色。如果您查看维基百科的Hue文章,您会发现色谱不是正弦波,而是红绿蓝的简单混合。以下是直观地解释我在说什么的图表:
http://en.wikipedia.org/wiki/File:HSV-RGB-comparison.svg
如果你使用正弦波代替波浪,它的最大值每60度一次达到峰值......当颜色值的斜率需要在每60度内保持不变时(即每一个周期内)在该期间内,颜色的最大值为255或最小值为0)
这在教程的帖子中提到了他的代码问题,但没有人发布它的分辨率......这是实际的分辨率:
//Define our variables
var nRadians:Number;
var nColor:int = 0;
var nX:Number;
var nY:Number;
var nIX:Number;
var nIY:Number;
var nR:Number;
var nG:Number;
var nB:Number;
// Calculate the thickness of the lines which draw the colors.
var iThickness:int = 1 + int(nRadius / 50);
// Loop from '0' to '360' degrees, drawing lines from the center
// of the wheel outward the length of the specified radius.
for(var i:int = 0; i < 360; i++)
{
nRadians = i * (Math.PI / 180);
var offset:Number = i;
do
{
offset = offset - 60;
} while (offset >= 60)
if (offset < 0) offset = offset + 60;
var greenSlope:String = "up";
var redSlope:String = "max";
var blueSlope:String = "min";
//GREEN-----------------
if (i >= 60) greenSlope = "max";
if (i > 180) greenSlope = "down";
if (i >= 240) greenSlope = "min";
//RED-------------------
if (i > 60) redSlope = "down";
if (i >= 120) redSlope = "min";
if (i > 240) redSlope = "up";
if (i >= 300) redSlope = "max";
//BLUE------------------
if (i > 120) blueSlope = "up";
if (i >= 180) blueSlope = "max";
if (i > 300) blueSlope = "down";
var colorArr:Array = new Array(blueSlope,greenSlope,redSlope);
var valueArr:Array = new Array(nB,nG,nR);
var counter:int = 0;
var bitRotation:int = 0;
for each (var color:String in colorArr)
{
var value:Number = 0;
var percentUpOffset:Number = ((100 / 60) * offset) / 100;
var percentDownOffset:Number = ((100 / 60) * (60 - offset)) / 100;
if (color == "max") value = 255;
if (color == "min") value = 0;
if (color == "up") value = 255 * percentUpOffset;
if (color == "down") value = 255 * percentDownOffset;
valueArr[counter] = value << bitRotation;
if (i == 0) trace(value);
bitRotation = bitRotation + 8;
counter++;
}
nR = valueArr[2];
nG = valueArr[1];
nB = valueArr[0];
// OR the individual color channels together.
nColor = nR | nG | nB;
// Calculate the coordinate in which the line should be drawn to.
// (nIX / nIY is the inner start position of the ring
nX = (nRadius * Math.cos(nRadians)) + DEFAULT_RADIUS;
nY = (nRadius * Math.sin(nRadians)) + DEFAULT_RADIUS;
nIX = ((nRadius - nHeight) * Math.cos(nRadians)) + DEFAULT_RADIUS;
nIY = ((nRadius - nHeight) * Math.sin(nRadians)) + DEFAULT_RADIUS;
//Draw the line
var line:Line = new Line();
var stroke:SolidColorStroke = new SolidColorStroke(nColor,iThickness);
line.stroke = stroke;
line.xFrom = nIX;
line.xTo = nX;
line.yFrom = nIY;
line.yTo = nY;
this.addElement(line);
}