skip to Main Content

I have code using d3 v6.7.0 that sets up a scale like so:

const range = [0, 828.156];
const domain = [[300,1],[300,2],[300,3],[400,1],[400,2],[400,3],[400,4]]
const scale = d3.scaleBand()
  .domain(domain)
  .range(range);

// test 1: this works in both v6 and v7
const a = domain[3];
console.log('array a', a);
console.log('scaled a:', scale(a));

// test 2: declaring a new, identical array to the one above, 
// also works in v6
const b = [400, 1];
console.log('array b', b);
console.log('scaled b:', scale(b));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js" integrity="sha512-cd6CHE+XWDQ33ElJqsi0MdNte3S+bQY819f7p3NUHgwQQLXSKjE4cPZTeGNI+vaxZynk1wVU3hoHmow3m089wA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

In d3 v7.9.0, this no longer works:

const range = [0, 828.156];
const domain = [[300,1],[300,2],[300,3],[400,1],[400,2],[400,3],[400,4]]

const scale = d3.scaleBand()
  .domain(domain)
  .range(range);

// test 1: this works in both v6 and v7
const a = domain[3];
console.log('array a', a);
console.log('scaled a:', scale(a));

// test 2:  declaring a new, identical array to the one above, 
// does not work in v7, but it does work in v6
const b = [400, 1];
console.log('array b', b);
console.log('scaled b:', scale(b));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.9.0/d3.min.js" integrity="sha512-vc58qvvBdrDR4etbxMdlTt4GBQk1qjvyORR2nrsPsFPyrs+/u5c3+1Ct6upOgdZoIl7eq6k3a1UPDSNAQi/32A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

Has something changed from v6 to v7, or what am I doing wrong?

2

Answers


  1. It looks like D3 v7.9.0 made a change in how the scaleBand function handles input data. For example, when you try to pass an array as ([400, 1]), it might not be interpreted correctly as an array with two elements [400, 1].

    Corrected Version

    const range = [0, 828.156];
    const domain = [[300,1],[300,2],[300,3],[400,1],[400,2],[400,3],[400,4]];
    
    const scale = d3.scaleBand()
      .domain(domain)
      .range(range);
    
    
    
    // corrected test 2 
    const b = [400, 1];
    console.log('array b', b);
    console.log('scaled b:', scale(b));
    
    Login or Signup to reply.
  2. D3 v7 uses InternMap:

    Ordinal scales now use InternMap for domains; domain values are now uniqued by coercing to a primitive value via object.valueOf instead of coercing to a string via object.toString.

    In v6 the domain would be coerced using object.toString:

    console.log([400,1].toString() === [400,1].toString())

    In v7 they use object.valueOf:

    console.log([400,1].valueOf() === [400,1].valueOf())
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search