Adjust text inside the bar of a d3 horizontal stacked bar

Viewed 39

I'm actually trying to make a horizontal stacked bar with text on each bar. I was able to get the text on each bar but there is one issue. There are bars which are very small and the text don't fit in them. How to make the text appear only on the bars that the text can fit or make the bar big enough for the text to fit?

enter image description here

var bars = svg.selectAll(null)
  .data(series)
  .enter()
  .append('g')
  .attr('fill', function (d) {
    return colorScale(d.key);
  })
  .selectAll('rect')
  .data(function (d) {
    return d;
  })
  .enter()
  .append('rect')
  .attr('x', function (d, i) {
    return xScale(d[0]);
  })
  .attr('width', function (d, i) {
    return xScale(d[1]) - xScale(d[0]);
  })
  .attr("height", yScale.bandwidth())
  .append("svg:title")
  .text(function (d) {
    return `${d[1] - d[0]}`;
  })    


  svg.selectAll('g').append("text")
  .attr('x', function (d, i) {
    return xScale(d[0][0]);
  })
  .style("text-anchor", "middle")
  .style("font-size", "26px")
  .style("font-family", "poppins_regular")
  .style("font-weight", "bold")
  .style("fill", "white")
  .attr("y", -5)
  .attr("dx", "1.8em")
  .attr("dy", "2em")
  .text(function (d) {
    return `${d['percent']} %`
  })
1 Answers

Use getBBox to compare the text width with the bar's one:

const text = svg.selectAll('g')
  .append("text")
  ...
  .text(d => `${d['percent']} %`);
  
text.each(function(d) {
  const isFullyVisible = this.getBBox().width < xScale(d[1]) - xScale(d[0]);
  d3.select(this).style('visibility', isFullyVisible ? 'visible' : 'hidden');
});

Related