当前位置:  开发笔记 > 编程语言 > 正文

如何选择饼图的颜色?

如何解决《如何选择饼图的颜色?》经验,为你挑选了5个好方法。

我有一些代码可以生成饼图的图像.它是一个通用类,因此任何数量的切片都可以作为输入.现在我有问题为切片选择好的颜色.有一些擅长的算法吗?

或者我应该亲自挑选并列出固定颜色?但是有多少.也许有10种颜色,希望永远不会超过10片?还有哪10种颜色可供选择?

颜色需要遵循一些规则:

他们需要看起来不错

相邻的颜色应该不相似(绿色旁边的蓝色是禁止的)

馅饼背景颜色是白色,所以白色是不可选择的

一些使用RGB值进行操作的算法将是首选解决方案.



1> Niels Bosma..:

我解决了如下:

    选择基色.

    计算它的色调(baseHue).

    创建具有相同饱和度和亮度的颜色,其色调计算如下:

      hue = baseHue + ((240 / pieces) * piece % 240
    

在C#中:

int n = 12;

Color baseColor = System.Drawing.ColorTranslator.FromHtml("#8A56E2");
double baseHue = (new HSLColor(baseColor)).Hue;

List colors = new List();
colors.Add(baseColor);

double step = (240.0 / (double)n);

for (int i = 1; i < n; ++i)
{
    HSLColor nextColor = new HSLColor(baseColor);
    nextColor.Hue = (baseHue + step * ((double)i)) % 240.0;
    colors.Add((Color)nextColor);
}

string colors = string.Join(",", colors.Select(e => e.Name.Substring(2)).ToArray());

我用过HSLColor类.

在谷歌图表例如使用12件和#8A56E2基色:

图表示例


在您的示例中,左上角的两种颜色(10小时到午夜)在我的屏幕上看起来完全相同!

2> Bill the Liz..:

我会预先编译一个大约20种颜色的列表,然后开始用第二种颜色重复.这样你就不会破坏你的第二条规则.此外,如果有人制作超过20个切片的饼图,他们会遇到更大的问题.:)


如果您真的需要~200种不同的颜色,您可能需要考虑使用Web安全调色板(或子集).http://en.wikipedia.org/wiki/Web_colors

3> Yarik..:

看看Color Brewer,这是一个有助于定义着色方案以传达定性或定量信息的工具:地图,图表等.这个工具可以生成的三种"类型"调色板 - 顺序,定性和分歧 -你可能需要后者,分歧......

您甚至可以下载包含所有调色板的RGB定义的Excel文件.



4> Pic Mickael..:

在此解决方案的基础上解决问题的规则#2,以下算法在饼的中间点周围交换颜色.这两个参数:

    pNbColors是饼图中的切片数

    pNonAdjacentSimilarColor一个布尔值,表示您是否要具有相邻的相似颜色.

我正在使用ColorHSL,ColorRGBColorUtils(下面提供).

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;
}

这会产生右侧输出:

比较图像

ColorHSL类:

    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类:

    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类:

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;
    }
}



5> Dave Jarvis..:
概观

从RGB转换为HSV然后调整色调(如此处所回答)会产生不一致的感知亮度.黄色/绿色明显比蓝色/紫色浅:

不符

没有这种变化的类似结果是可能的:

一贯

算法

然而,该算法要复杂得多:

    将HTML十六进制代码转换为标称RGB值(将分量除以255).

    将RGB值转换为XYZ颜色空间 ; 使用D65参考白色 sRGB 工作空间.

    从XYZ转换为L a b颜色空间.

    从L a b 转换为LCH颜色空间.

    计算LCH颜色空间中的饼图颜色色调:

    (360.0 div $wedges) * $wedge

    用弧度重新计算新的色调.

    使用新色调从LCH转换回L a b颜色空间.

    从L a b 转换为XYZ颜色空间.

    从XYZ转换为sRGB色彩空间.

    将RGB值乘以255.

履行

以下是XSLT 1.0中的示例实现:




















  
  
  
  
  
  

  
  
    
      
    
  
  
    
      
    
  
  
    
      
    
  

  
  
  
  

  
  
  
  

  
  
    
      
    
  
  
    
      
    
  
  
    
      
    
  

  
  
  

  
  

  
    
      
    
  

  
    
      
      
    
  

  
  
  
  
    
      
        
        
      
      
        
      
    
  
  
  

  
  
    
      
    
  
  
    
      
    
  

  
  
  

  
  
  
  

  
    
      
      
    
  
  
    
      
      
    
  

  
    
      
        
      
      
        
      
    
  
  
    
      
        
          
          
        
      
      
        
      
    
  
  
    
      
        
      
      
        
      
    
  

  
  
  

  
  
  
  

  
  
  
  

  rgb(
  
  )



  

  
    
      
        
        
      
    
    
      
    
  




  

  
  
  
  
  
  



trig,root和其他数学函数留给读者练习.此外,没有人在他们正确的思想中想要在XSLT 1.0中编写所有这些代码.另一方面,XSLT 2.0在这里有一个实现.

资源

进一步阅读:

使用直观参数生成调色板

彩色调色板的合成

有用的颜色方程

色彩空间简介

在感知连贯的空间中均匀分布的颜色

一种选择高对比度颜色集的算法

选择统计图形的颜色

Colourspace转换

布鲁尔调色板

推荐阅读
跟我搞对象吧
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有