如何使用d3生成尽可能多的颜色?

时间:2013-12-30 20:39:02

标签: javascript svg d3.js

我正在使用d3.js构建一个饼图,并可视化一个大数据集。在图表上可视化的内容超过 137项。我使用此功能只有 10种颜色

d3.scale.category10().range()

通过探索其他选项: https://github.com/mbostock/d3/wiki/Ordinal-Scales

d3.scale.category20().range()

var chart = nv.models.pieChart()
    .x(function(d) {
        return d.key
    })
    .y(function(d) {
        return d.y
    })
    .color(d3.scale.category10().range())
    .width(width)
    .height(height);

如何使用d3生成任意数量的颜色?

8 个答案:

答案 0 :(得分:20)

我遇到了同样的问题,所以我写了一个小工具来生成很多感知上不同的颜色:category color generator

此工具可生成颜色列表。然后,您可以使用该列表:

color = d3.scale.ordinal()
    .domain(YOUR_DATA_CATEGORIES)
    .range(["#30c514", "#9321ff", ...]);

如果两个亮度不够,还有一个generalised version

以下是一些pre-generated example colour sets

答案 1 :(得分:12)

当你使用很多类别时,不可能使用感知上不同的颜色。好消息是,在饼图中,每个旁边只有两种颜色,然后所有颜色都不需要不同,只需要相邻。

我要做的是使用d3.interpolateHcl()生成两种不同的色标。 HCL和Lab是产生自然色彩渐变的更好的颜色模型,也是category20()用于生成感知上不同颜色的颜色。

var colorScales =[
  d3.scale.linear()
    .interpolate(d3.interpolateHcl) 
    .range(["#9AF768", "#F27A4D"]),
  d3.scale.linear()
    //.domain([0,1])
    .interpolate(d3.interpolateHcl) 
    .range(["#112231","#3C769D"])
];

将您想要的颜色放在range([...])中并应用这些功能添加一些随机性。我正在使用数据的索引i在两种配色方案之间交替。

.color(function(d,i) {
  return colorScales[i%2]       
          (Math.random());
})

有关色彩理论和色彩模型的更多信息:

一个好的HCL色彩空间颜色选择器:

<强>更新

较新版本的d3提供了更多颜色方案和插值器with more sophisticated models。有一些类型的方案,我认为这个用例最有用的是the sequential multi-hue interpolators

我开发了一个交互式小部件来探索这些比例和插值器,同时改变颜色的数量。见下文。

注意,使用这些方案提供几种感知上不同的颜色也很困难。

const categorical = [{
    "name": "interpolateViridis"  },
  { "name": "interpolateInferno"  },
  { "name": "interpolateMagma"    },
  { "name": "interpolatePlasma"   },
  { "name": "interpolateWarm"     },
  { "name": "interpolateCool"     },
  { "name": "interpolateCubehelixDefault"  },
  { "name": "interpolateRainbow"  },
  { "name": "interpolateSinebow"  }
]

const width = 600,
  height = 80;

const svg = d3.select("body")
  .append("svg")
  .attr("width", width)
  .attr("height", height)
  .append("g")


const unit = (s) => width / s.n;
const state = {
  n: 12,
  colorScale: d3.scaleSequential(d3[categorical[8].name])
};

const update = () => {

  bars.data(d3.range(0, 1, 1 / state.n))
    .enter().append("rect")
    .attr("class", "bars")
    .attr("y", 0)
    .attr("height", height)
    .attr("width", unit(state))
    .attr("x", (d, i) => i * unit(state))
    .style("fill", state.colorScale)
    .merge(bars);
    
  bars.exit().remove();

}

const bars = svg.selectAll(".bars");

update()

const sequentialButtons = d3.select(".categoricalButtons")
  .selectAll("button")
  .data(categorical)
  .enter().append("button")
  .text(d => d.name)
  .on("click",  (buttonValue) =>{ 
    state.colorScale = d3.scaleSequential(d3[buttonValue.name]);
    update();
    });

const itemsInput = d3.select('#items')
  .on('change',(d,i,arr)=>{
    state.n = arr[i].value;
    update();
    });
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

<div class="categoricalButtons">Color Scales: </div>
<div><input id="items" type="number" value="12"></div>

答案 2 :(得分:8)

我们可以使用自定义颜色,例如您可以创建自己的颜色范围:.range(["#fff","#000","#333"]);。这是一个类似的StackOverflow线程:https://stackoverflow.com/a/13013162/1848540

答案 3 :(得分:1)

你不能使用d3获得超过20种颜色,因为它的硬编码颜色列表 (你可以在这里看到代码 - https://github.com/mbostock/d3/blob/master/src/scale/category.js

答案 4 :(得分:0)

您可以在this code中尝试无限颜色生成器。最简单的变体将转化为:

function color_inf (n, base, saturation, lightness) {
    // base: natural number from 2 to something small (like 5)
    // saturation and lightness - numbers from 0 to 1
    var tmp = i.toString(base).split("").reverse().join("");
    var hue = 360 * parseInt(tmp, base) / Math.pow(base, tmp.length);
    return d3.hsl(hue, saturation, lightness);
}

更先进的将使用饱和度和亮度的变化 - 连续衰减/饱和度,周期性或与色调类似的方式。

Nut会被警告 - 当你使用超过20种颜色时,无论你的刻度有多好(并且无限大小都没有针对所有颜色数量进行优化),人们在区分它们时会遇到问题(除非并排)。

答案 5 :(得分:0)

如果你有那么多类别,那么饼图就是错误的作业图表。你能总结(分组)这些类别吗?

你也考虑过这个工作的星爆图(再次需要分组)。

Stephen Few(数据专家和作者)建议在图表上不超过9种颜色(类别)。

答案 6 :(得分:0)

我遇到了同样的问题,所以使用这个solution,我扩展它以便它可以用来生成437种颜色,我使用上面提到的颜色生成器来生成这种颜色。

d3.scale.category437 = function() {
return d3.scale.ordinal().range(d3_category437);
};

var d3_category437 = [
0xd3fe14, 0xfec7f8, 0x0b7b3e, 0x0bf0e9, 0xc203c8, 0xfd9b39, 0x888593, 
0x906407, 0x98ba7f, 0xfe6794, 0x10b0ff, 0xac7bff, 0xfee7c0, 0x964c63, 
0x1da49c, 0x0ad811, 0xbbd9fd, 0xfe6cfe, 0x297192, 0xd1a09c, 0x78579e, 
0x81ffad, 0x739400, 0xca6949, 0xd9bf01, 0x646a58, 0xd5097e, 0xbb73a9, 
0xccf6e9, 0x9cb4b6, 0xb6a7d4, 0x9e8c62, 0x6e83c8, 0x01af64, 0xa71afd, 
0xcfe589, 0xd4ccd1, 0xfd4109, 0xbf8f0e, 0x2f786e, 0x4ed1a5, 0xd8bb7d, 
0xa54509, 0x6a9276, 0xa4777a, 0xfc12c9, 0x606f15, 0x3cc4d9, 0xf31c4e, 
0x73616f, 0xf097c6, 0xfc8772, 0x92a6fe, 0x875b44, 0x699ab3, 0x94bc19, 
0x7d5bf0, 0xd24dfe, 0xc85b74, 0x68ff57, 0xb62347, 0x994b91, 0x646b8c, 
0x977ab4, 0xd694fd, 0xc4d5b5, 0xfdc4bd, 0x1cae05, 0x7bd972, 0xe9700a, 
0xd08f5d, 0x8bb9e1, 0xfde945, 0xa29d98, 0x1682fb, 0x9ad9e0, 0xd6cafe, 
0x8d8328, 0xb091a7, 0x647579, 0x1f8d11, 0xe7eafd, 0xb9660b, 0xa4a644, 
0xfec24c, 0xb1168c, 0x188cc1, 0x7ab297, 0x4468ae, 0xc949a6, 0xd48295, 
0xeb6dc2, 0xd5b0cb, 0xff9ffb, 0xfdb082, 0xaf4d44, 0xa759c4, 0xa9e03a, 
0x0d906b, 0x9ee3bd, 0x5b8846, 0x0d8995, 0xf25c58, 0x70ae4f, 0x847f74, 
0x9094bb, 0xffe2f1, 0xa67149, 0x936c8e, 0xd04907, 0xc3b8a6, 0xcef8c4, 
0x7a9293, 0xfda2ab, 0x2ef6c5, 0x807242, 0xcb94cc, 0xb6bdd0, 0xb5c75d, 
0xfde189, 0xb7ff80, 0xfa2d8e, 0x839a5f, 0x28c2b5, 0xe5e9e1, 0xbc79d8, 
0x7ed8fe, 0x9f20c3, 0x4f7a5b, 0xf511fd, 0x09c959, 0xbcd0ce, 0x8685fd, 
0x98fcff, 0xafbff9, 0x6d69b4, 0x5f99fd, 0xaaa87e, 0xb59dfb, 0x5d809d, 
0xd9a742, 0xac5c86, 0x9468d5, 0xa4a2b2, 0xb1376e, 0xd43f3d, 0x05a9d1, 
0xc38375, 0x24b58e, 0x6eabaf, 0x66bf7f, 0x92cbbb, 0xddb1ee, 0x1be895, 
0xc7ecf9, 0xa6baa6, 0x8045cd, 0x5f70f1, 0xa9d796, 0xce62cb, 0x0e954d, 
0xa97d2f, 0xfcb8d3, 0x9bfee3, 0x4e8d84, 0xfc6d3f, 0x7b9fd4, 0x8c6165, 
0x72805e, 0xd53762, 0xf00a1b, 0xde5c97, 0x8ea28b, 0xfccd95, 0xba9c57, 
0xb79a82, 0x7c5a82, 0x7d7ca4, 0x958ad6, 0xcd8126, 0xbdb0b7, 0x10e0f8, 
0xdccc69, 0xd6de0f, 0x616d3d, 0x985a25, 0x30c7fd, 0x0aeb65, 0xe3cdb4, 
0xbd1bee, 0xad665d, 0xd77070, 0x8ea5b8, 0x5b5ad0, 0x76655e, 0x598100, 
0x86757e, 0x5ea068, 0xa590b8, 0xc1a707, 0x85c0cd, 0xe2cde9, 0xdcd79c, 
0xd8a882, 0xb256f9, 0xb13323, 0x519b3b, 0xdd80de, 0xf1884b, 0x74b2fe, 
0xa0acd2, 0xd199b0, 0xf68392, 0x8ccaa0, 0x64d6cb, 0xe0f86a, 0x42707a, 
0x75671b, 0x796e87, 0x6d8075, 0x9b8a8d, 0xf04c71, 0x61bd29, 0xbcc18f, 
0xfecd0f, 0x1e7ac9, 0x927261, 0xdc27cf, 0x979605, 0xec9c88, 
0x8c48a3,0x676769, 0x546e64, 0x8f63a2, 0xb35b2d, 0x7b8ca2, 0xb87188, 
0x4a9bda, 0xeb7dab, 0xf6a602, 0xcab3fe, 0xddb8bb, 0x107959, 0x885973, 
0x5e858e, 0xb15bad, 0xe107a7, 0x2f9dad, 0x4b9e83, 0xb992dc, 0x6bb0cb, 
0xbdb363, 0xccd6e4, 0xa3ee94, 0x9ef718, 0xfbe1d9, 0xa428a5, 0x93514c, 
0x487434, 0xe8f1b6, 0xd00938, 0xfb50e1, 0xfa85e1, 0x7cd40a, 0xf1ade1, 
0xb1485d, 0x7f76d6, 0xd186b3, 0x90c25e, 0xb8c813, 0xa8c9de, 0x7d30fe, 
0x815f2d, 0x737f3b, 0xc84486, 0x946cfe, 0xe55432, 0xa88674, 0xc17a47, 
0xb98b91, 0xfc4bb3, 0xda7f5f, 0xdf920b, 0xb7bbba, 0x99e6d9, 0xa36170, 
0xc742d8, 0x947f9d, 0xa37d93, 0x889072, 0x9b924c, 0x23b4bc, 0xe6a25f, 
0x86df9c, 0xa7da6c, 0x3fee03, 0xeec9d8, 0xaafdcb, 0x7b9139, 0x92979c, 
0x72788a, 0x994cff, 0xc85956, 0x7baa1a, 0xde72fe, 0xc7bad8, 0x85ebfe, 
0x6e6089, 0x9b4d31, 0x297a1d, 0x9052c0, 0x5c75a5, 0x698eba, 0xd46222, 
0x6da095, 0xb483bb, 0x04d183, 0x9bcdfe, 0x2ffe8c, 0x9d4279, 0xc909aa, 
0x826cae, 0x77787c, 0xa96fb7, 0x858f87, 0xfd3b40, 0x7fab7b, 0x9e9edd, 
0xbba3be, 0xf8b96c, 0x7be553, 0xc0e1ce, 0x516e88, 0xbe0e5f, 0x757c09, 
0x4b8d5f, 0x38b448, 0xdf8780, 0xebb3a0, 0xced759, 0xf0ed7c, 0xe0eef1, 
0x0969d2, 0x756446, 0x488ea8, 0x888450, 0x61979c, 0xa37ad6, 0xb48a54, 
0x8193e5, 0xdd6d89, 0x8aa29d, 0xc679fe, 0xa4ac12, 0x75bbb3, 0x6ae2c1, 
0xc4fda7, 0x606877, 0xb2409d, 0x5874c7, 0xbf492c, 0x4b88cd, 0xe14ec0, 
0xb39da2, 0xfb8300, 0xd1b845, 0xc2d083, 0xc3caef, 0x967500, 0xc56399, 
0xed5a05, 0xaadff6, 0x6685f4, 0x1da16f, 0xf28bff, 0xc9c9bf, 0xc7e2a9, 
0x5bfce4, 0xe0e0bf, 0xe8e2e8, 0xddf2d8, 0x9108f8, 0x932dd2, 0xc03500, 
0xaa3fbc, 0x547c79, 0x9f6045, 0x04897b, 0x966f32, 0xd83212, 0x039f27, 
0xdf4280, 0xef206e, 0x0095f7, 0xa5890d, 0x9a8f7f, 0xbc839e, 0x88a23b, 
0xe55aed, 0x51af9e, 
0x5eaf82, 0x9e91fa, 0xf76c79, 0x99a869, 0xd2957d, 0xa2aca6, 0xe3959e, 
0xadaefc, 0x5bd14e, 0xdf9ceb, 0xfe8fb1, 0x87ca80, 0xfc986d, 0x2ad3d9, 
0xe8a8bb, 0xa7c79c, 0xa5c7cc, 0x7befb7, 0xb7e2e0, 0x85f57b, 0xf5d95b, 
0xdbdbff, 0xfddcff, 0x6e56bb, 0x226fa8, 0x5b659c, 0x58a10f, 0xe46c52, 
0x62abe2, 0xc4aa77, 0xb60e74, 0x087983, 0xa95703, 0x2a6efb, 0x427d92
].map(d3_rgbString);


function d3_rgbString (value) {
return d3.rgb(value >> 16, value >> 8 & 0xff, value & 0xff);
}

这不是一个好的解决方案。将来会尝试自动生成颜色字符串。

答案 7 :(得分:0)

一个尚未使我感到惊讶的简单解决方案(使用d3 @ 5,尚不确定早期版本)是将插值函数与一个函数结合使用以得出您的[0,1]比率类别对应于类别集。

     const color = d3.interpolateSpectral;

     //...

     .style("color", (d:any, i:number) => {
       const t:number = i / data.columns.length;
       return color(t) as string;
    });

https://github.com/d3/d3-scale-chromatic