gaitat
gaitat

Reputation: 12632

tick format produces overlapping labels

I am currently using:

var formatValue = d3.format("s");

and then

var axisX = d3.svg.axis()
    .scale( someXscale )
    .tickFormat (function( d ) { return formatValue(d); } );

This code produces the following when I zoom (from the highest zoom to the lowest):

enter image description here enter image description here enter image description here enter image description here enter image description here enter image description here enter image description here enter image description here enter image description here enter image description here

The values on this axis can go up to 3,100,000,000.

I don't like the fact that the values fall on top of each other and less important I would like the labels to have Giga, Mega, Kilo.

I would appreciate any suggestions.

Upvotes: 1

Views: 265

Answers (1)

Aurelio
Aurelio

Reputation: 25792

A good way can be drawn from this comment by M. Bostock:

var formatAbbreviation = d3.format(".2s");

formatAbbreviation(5000000000); // 5.00G
formatAbbreviation(5000000); // 5.00M
formatAbbreviation(5000); // 5.00k

In the post you see him actually customising the behaviour, changing G to B.

I actually created my own custom implementation in the past, maybe it can be useful. Here's an example I've made:

var format = function(num) {
  var numToStr = num + '';
  var ext = ['', 'K', 'M', 'G']; // Add extensions as needed
  var size = 3; 
  var val = 0;
  var max = 5; // how many digit maximum we want on screen

  var compress = function(str) {
    var len = str.length;
    if (len <= size) {
      return str + ext[val];
    }
    if (val + 1 === ext.length) {
      return str.slice(0, max) + ext[val]; // <= what to do when the max number of digits is reached, change as needed
    }      
    val++;
    return compress(str.slice(0, str.length - size));
  }
  return compress(numToStr);
}

console.log(format(1)) // => 1
console.log(format(12)) // => 12
console.log(format(123)) // => 123
console.log(format(1234)) // => 1K
console.log(format(12345)) // => 12K
console.log(format(123456)) // => 123K
console.log(format(1234567)) // => 1M
console.log(format(12345678)) // => 12M
console.log(format(123456789)) // => 123M
console.log(format(1234567890)) // => 1G
console.log(format(12345678901)) // => 12G
console.log(format(12345678902321312)) // => 12345G

// used more or less like so in d3
var axisX = d3.svg.axis()
    .scale( someXscale )
    .tickFormat (function( d ) { return format(d); } );

As you notice we can define the maximum number of digits you want on screen - in this case 5 - and handle that case as we think it's best for the particular situation (every case is different).

Upvotes: 1

Related Questions