web-dev-qa-db-fra.com

Comment puis-je générer autant de couleurs que je veux en utilisant d3?

Je construis un graphique à secteurs avec d3.js et visualise un grand ensemble de données. Il y a plus de 137 éléments à visualiser sur le graphique. Je viens de 10 couleurs en utilisant cette fonction.

d3.scale.category10().range()

en explorant d'autres options: 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);

Comment puis-je générer autant de couleurs que je veux en utilisant d3?

12
user3147036

J'ai eu le même problème, alors j'ai écrit un petit outil pour générer BEAUCOUP de couleurs différentes du point de vue de la perception: générateur de couleur de catégorie .

Cet outil produit une liste de couleurs. Vous pouvez ensuite utiliser cette liste comme:

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

Il existe également une version généralisée si deux éclaircies ne suffisent pas.

Voici quelques exemples de jeux de couleurs pré-générés .

19
jnnnnn

Comme vous utilisez beaucoup de catégories, il est impossible d’utiliser des couleurs différentes du point de vue de la perception. La bonne nouvelle est que, dans un diagramme à secteurs, seules deux couleurs sont adjacentes, alors toutes ne doivent pas nécessairement être différentes, mais uniquement celles qui sont adjacentes.

Ce que je voudrais faire, c'est générer deux échelles de couleurs différentes, toutes deux utilisant d3.interpolateHcl(). HCL et Lab sont de meilleurs modèles de couleur pour générer des dégradés de couleurs naturels et sont également ce que category20() a utilisé pour générer des couleurs perceptuellement différentes.

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

Mettez les couleurs que vous voulez dans la range([...]) et appliquez ces fonctions en ajoutant un peu de hasard. J'utilise l'index i des données pour alterner les deux jeux de couleurs.

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

Plus sur la théorie des couleurs et les modèles de couleurs:

Et un bon colorpicker d’espace colorimétrique HCL:

UPDATE

Les nouvelles versions de d3 fournissent davantage de jeux de couleurs et d'interpolateurs avec des modèles plus sophistiqués . Il existe certains types de schémas et je pense que les plus utiles pour ce cas d'utilisation sont les interpolateurs séquentiels à teintes multiples

J'ai développé un widget interactif pour explorer ces échelles et interpolateurs tout en modifiant le nombre de couleurs. Voir ci-dessous.

Notez qu’il est également difficile avec ces schémas de fournir plusieurs couleurs perceptuellement différentes.

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>

10
David Lemon

Nous pouvons utiliser des couleurs personnalisées. Par exemple, vous pouvez créer votre propre gamme de couleurs: .range(["#fff","#000","#333"]);. Voici un thread StackOverflow similaire: https://stackoverflow.com/a/13013162/1848540

8
id.ot

Vous ne pouvez pas utiliser d3 pour obtenir plus de 20 couleurs car sa liste de couleurs codées en dur (Vous pouvez voir ici le code - https://github.com/mbostock/d3/blob/master/src/scale /category.js )

1
Zachia

J'ai rencontré le même problème, alors en utilisant cette solution , je l'ai développée pour qu'elle puisse être utilisée générer 437 couleurs, j'ai utilisé le générateur de couleurs mentionné ci-dessus pour générer ces couleurs. 

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

Ce n'est pas une bonne solution. Je vais essayer de générer la chaîne de couleur automatique à l'avenir. 

0
radhikesh93

Si vous avez autant de catégories, alors un diagramme à secteurs est le mauvais diagramme pour le travail. Pouvez-vous résumer (grouper) les catégories?

Avez-vous également envisagé de créer un diagramme en étoile pour le travail (encore une fois, il faut le regrouper).

Stephen Few (expert en données et auteur) recommande au maximum 9 couleurs (catégories) sur un graphique.

0
jamesleesaunders

Vous pouvez essayer un générateur de couleurs infini comme dans ce code . La variante la plus simple se traduirait par:

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

Plus avancé utiliserait des changements de saturation et de luminosité - soit une décroissance/saturation continue, périodique, ou d'une manière similaire à celle de la teinte.

Nut be warned - lorsque vous utilisez plus de 20 couleurs, quelle que soit la qualité de votre échelle (et l'échelle infinie n'est pas optimisée pour all nombre de couleurs), vous aurez du mal à les distinguer (sauf si côte à côte) ).

0
Piotr Migdal