Ordinal scale behaviour

后端 未结 1 995
清酒与你
清酒与你 2021-01-14 14:16

I would like to create an ordinal scale with one to one correspondence between range and domain. I would expect that values/strings that do not belong to the domain would re

相关标签:
1条回答
  • 2021-01-14 14:26

    That's the expected behaviour of an ordinal scale. Actually, D3 scales (quantitative or qualitative) are made in such a way that you can pass values outside the domain (see my answer here).

    If you want to define outputs for unknown inputs, use scale.unknown():

    var x = d3.scaleOrdinal()
        .domain(['a', 'b', 'c'])
        .range([10, 20, 30])
        .unknown("not in the scale");
    
    console.log("a is " + x("a"));
    console.log("b is " + x("b"));
    console.log("c is " + x("c"));
    console.log("f is " + x("f"));
    console.log("xyz is " + x("xyz"));
    <script src="https://d3js.org/d3.v4.min.js"></script>

    EDIT: Regarding OP's question in the comments:

    Are the range values for values outside the domain chosen randomly or is there a logic?

    The logic can be seen inspecting the source code:

    function scale(d) {
        var key = d + "", i = index.get(key);
        if (!i) {
            if (unknown !== implicit) return unknown;
            index.set(key, i = domain.push(d));
        }
        return range[(i - 1) % range.length];
    }
    

    It shows us that, if the value doesn't exist, it's pushed into the domain. So, values not specified in the domain will have an output that will "cycle" through the range. Check this demo, the output is 10, 20, 30, 10, 20, 30, 10, 20...:

    var x = d3.scaleOrdinal()
        .domain(['a', 'b', 'c'])
        .range([10, 20, 30]);
    
    console.log("d is " + x("d"));
    console.log("e is " + x("e"));
    console.log("f is " + x("f"));
    console.log("g is " + x("g"));
    console.log("h is " + x("h"));
    console.log("i is " + x("i"));
    console.log("j is " + x("j"));
    <script src="https://d3js.org/d3.v4.min.js"></script>

    Which has the same outcome of writing this:

    var x = d3.scaleOrdinal()
    .domain(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'])
    .range([10, 20, 30]);
    

    In this case d corresponds to 10, e corresponds to 20, f corresponds to 30 etc...

    0 讨论(0)
提交回复
热议问题