d3.scale.category10() not behaving as expected

前端 未结 3 2131
走了就别回头了
走了就别回头了 2020-12-14 08:11

I\'m encountering unexpected behavior when using d3.scale.category10() to generate 10 fixed colors.

Starting out, I note that colors.range() returns an array of pro

3条回答
  •  暗喜
    暗喜 (楼主)
    2020-12-14 08:33

    It turns out that setting the scale's domain remedies this issue.

    var colors = d3.scale.category10().domain([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
    
    // Now this will return the first item instead of the zeroth.
    console.log(colors(1)); 
    

    Or somewhat more succinctly,

    var colors = d3.scale.category10().domain(d3.range(0,10));
    

    Updated fiddle: http://jsfiddle.net/LqHst/2/

    When the category10 scale is created, it's created with a range of 10 colors, and an empty domain.

    var colors = d3.scale.category10();
    console.log(colors.range()); // -> ["#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf"]
    console.log(colors.domain()); // -> []
    

    According to the documentation (and the accepted answer), setting the domain on an ordinal scale is optional. When no domain is set, its values are assumed from calls to the scale function.

    var colors = d3.scale.category10();
    console.log(colors.domain()); // -> []
    console.log(colors(1)); // -> #1f77b4
    console.log(colors.domain()); // -> [1]
    console.log(colors(0), colors(3), colors(7)); // -> #ff7f0e #2ca02c #d62728
    console.log(colors.domain()); // -> [1, 0, 3, 7] 
    

    Only if the given index is not already in the domain does it get added.

    This is why the workaround, as stated in the original question, produced the expected behavior. Stepping through the scale via a for loop queried the scale in natural order, adding ordered indices to the domain.

    var colors = d3.scale.category10();
    
    for (var i = 0; i < 10; i++) {
        colors(i)
    }
    
    console.log(colors.domain()); // -> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    

    The moral of the story is to set the domain explicitly, in order to get more predictable behavior, as shown at the top of this answer.

提交回复
热议问题