Alina Khachatrian
Alina Khachatrian

Reputation: 757

D3 same ticks being showed twice on y axis

Same ticks value being displayed multiple times (1M in this case) on y axis. I don't think the problem is in how I'm formatting the ticks with yAxisTickFormat. What am I doing wrong?

CodeSandbox

export const yAxisTickFormat = (d) => {
  //Logic to reduce big numbers
  const limits = [1000000, 10000, 1000];
  const shorteners = ['M', 'K', 'K'];
  for (let i in limits) {
    if (d > limits[i]) {
      return (d / limits[i]).toFixed() + shorteners[i];
    }
  }
  return d;
};

const maxValue = storeData.dataset.reduce((maxAll, item) => {
  return item.values.reduce((maxItem, val) => 
    Math.max(maxItem, val.value), maxAll);
}, 0);
    
const yScale = d3.scaleLinear().range([-120, height - 200]);

yScale.domain([maxValue, 0]);

 const yAxis = d3
  .axisLeft()
  .scale(yScale)
  .tickFormat((d) => (d === 0 ? null : '£') + yAxisTickFormat(d))
  .ticks(5)
  .tickSize(-width, barMargin, 0)
  .tickPadding(10);

enter image description here

Upvotes: 1

Views: 146

Answers (2)

Michael Rovinsky
Michael Rovinsky

Reputation: 7210

Here is a more correct yAxisTickFormat (tested with a snippet):

const yAxisTickFormat = (d) => {
  let limit = Math.pow(10, 12);
  const shorteners = ["T", "B", "M", "K"];
  for (let i = 0; i < shorteners.length; i++) {
    if (d >= limit) {
      const zeroPad = Math.floor(d / limit) === d / limit;
      return '£ ' + (d / limit).toFixed(zeroPad ? 0 : 1) + ' ' + shorteners[i];
    }
    limit /= 1000;
  }
  return d;
};

const svg = d3.select('svg');

const ranges = [5000, 2000000, 4000000000, 3500000000000];

ranges.forEach((range, index) => {
    const yScale = d3.scaleLinear().domain([range, 0]).range([0,300]);

const yAxis = d3
      .axisLeft()
      .scale(yScale)
      .tickFormat((d) => yAxisTickFormat(d))
      .ticks(10);
      
 svg.append('g').attr('transform', `translate(${50 + index * 100},50)`).call(yAxis);     
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="400" height="400"/>

Upvotes: 2

t1m0n
t1m0n

Reputation: 3431

On the contrary, problem is in number formating. You are passing 1400000 and 1200000 which are converts to 1M. Try to add several digits after comma by passing argument to .toFixed method

export const yAxisTickFormat = (d) => {
  //Logic to reduce big numbers
  const limits = [1000000, 10000, 1000];
  const shorteners = ['M', 'K', 'K'];
  for (let i in limits) {
    if (d > limits[i]) {
      return (d / limits[i]).toFixed(1) + shorteners[i];
    }
  }
  return d;
};

Which will convert your numbers to 1.4m and 1.2m accordingly.

Upvotes: 2

Related Questions