You misunderstand the usage of category10
.
As the document mentioned: d3.scale.category10()
constructs a new ordinal scale with a range of ten categorical colors.
That is to say: var color = d3.scale.category10()
will construct a new ordinal scale with empty domain and range with ten colors.
When you use the ordinal scale:
If no domain is set, a range must be set explicitly. Then, each unique value that is passed to the scale function will be assigned a new value from the output range; in other words, the domain will be inferred implicitly from usage. Although domains may thus be constructed implicitly,
https://github.com/mbostock/d3/wiki/Ordinal-Scales#wiki-ordinal_domain you can read the API of ordinal scale for more information.
Update: an ordinal-scale is a map, not an array.
If domain is not set explicit, the domain will be construct implicit with the key sequence you invoke color(key).
var color = d3.scale.category10();
console.log(color.domain()); // []
color("aaa");
console.log(color.domain()); // ["aaa"]
color("bbb");
console.log(color.domain()); // ["aaa", "bbb"]
color("ccc");
console.log(color.domain()); // ["aaa", "bbb", "ccc"]
This is useful when you just want to assign a different color for different clusters, and don't have a fixed color mapping. (Think about the situation: when your program support user upload data file as the data source.)
If you want to map each category to specific color, you have to set the domain explicit so that the mapping is not depend on the sequence of keys.
var color = d3.scale.category10();
var domain = ["bbb", "ddd", "ccc", "23", "hello"];
color.domain(domain);
console.log(color.domain()); // ["bbb", "ddd", "ccc", "23", "hello"]
console.log(color.range()); // ["#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf"]
color("ddd"); // "#ff7f0e" : d3 will get index of "ddd" and return range[index]