I'm using d3 to display the number of persons in a group. Based on how the user filter, it can be more than 100k or a single digit number
I tried d3.format(".2s"), and it works well most of the time, but I have two problems:
My ideal format function would display the integer with the maximum precision possible in a fixed maximum number of characters/numbers. so if I want to limit the display to 3 numbers/4 chars, it would:
is there a way to specify a maximum display size instead of a specific precision?
(and before any mathematician burns me to have such a cavalier attitude to precision, the number display is to give an indication, the users always have an option to see the real number, without any loss of precision ;)
You can achieve it by specifying custom formatting function. If I understand you correctly, it should look like this:
function customFormat(value) {
    var formattedValue = value;
  if (value > 999 && value < 100000) {
    if (value % 1000 < 50) {
        formattedValue = d3.format('.0s')(value);
    } else {
        formattedValue = d3.format('.2s')(value);
    }
  } else if (value >= 100000) {
    formattedValue = d3.format('.3s')(value);
  }
    return formattedValue;
}
Little demo how it works:
var svgOne = d3.select("#scale-one")
    .append("svg")
    .attr("width", 500)
    .attr("height", 50)
    .append("g")
    .attr("transform", "translate(20,0)");
var svgTwo = d3.select("#scale-two")
    .append("svg")
    .attr("width", 500)
    .attr("height", 100)
    .append("g")
    .attr("transform", "translate(20,0)");
    
var x = d3.scaleLinear()
	.range([0,490])
  .domain([0,2000]);
function customFormat(value) {
	var formattedValue = value;
  
  if (value > 999 && value < 100000) {
    if (value % 1000 < 50) {
    	formattedValue = d3.format('.0s')(value);
    } else {
    	formattedValue = d3.format('.2s')(value);
    }
  } else if (value >= 100000) {
    formattedValue = d3.format('.3s')(value);
  }
  
	return formattedValue;
}
var xAxis = d3.axisBottom(x)
	.tickValues([8, 777, 1049, 1750])
  .tickFormat(customFormat);
var xLargeNumbers = d3.scaleLinear()
	.range([0,490])
  .domain([123000, 126000]);
  
var xAxisLargeNumbers = d3.axisBottom(xLargeNumbers)
	.tickValues([123499, 123999])
  .tickFormat(customFormat);
  
svgOne.append("g")
		.attr("class", "x axis")
    .attr("transform", "translate(0,5)")
    .call(xAxis);
svgTwo.append("g")
		.attr("class", "x axis")
    .attr("transform", "translate(0,5)")
    .call(xAxisLargeNumbers);
<script src="https://d3js.org/d3.v4.js"></script>
<div>Ticks: [8, 777, 1049, 1750] -</div>
<div id="scale-one"></div>
<div>Ticks: [123499, 123999] -</div>
<div id="scale-two"></div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With