2
votes

I have created a codepen demonstrating my issue. Basically, my axis labels are being created successfully, and are added to the DOM but they are not displaying because they're getting drawn outside of the chart area.

Here is my CSS:

.promo {
  fill: rgba(255,0,0,0.5);
}

.price {
  fill: $brand-primary;
}

.chart {
  height: 50vh;
  width: 100%;
  overflow: hidden;
}

.svg-container {
    display: inline-block;
    position: relative;
    width: 100%;
    padding-bottom: 100%; /* aspect ratio */
    vertical-align: top;
    overflow: hidden;
}
.svg-content-responsive {
    display: inline-block;
    position: absolute;
    top: 0;
    left: 0;
}

And my JS:

let height = $('.chart').height();
let width = $('.chart').width();

let chart = d3.select('.chart')
    .append("div")
    .classed("svg-container", true) //container class to make it responsive
    .append("svg")
    .attr('preserveAspectRatio','xMinYMax meet')
    .attr('viewBox','0 0 '+width +' '+height )
    .classed("svg-content-responsive", true)
    .append('g');
    //.attr("transform", "translate(50 0)");

let tip = d3.tip()
            .attr('class', 'd3-tip')
            .offset([-10, 0])
            .html(function(d) {
              let date = new Date(d[0]);
              let year = date.getFullYear();
              let allMonths = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
              let month = allMonths[date.getMonth()];
              return `<strong>$${d[1]} Billion</strong><br>${year} - ${month}`;
            });

chart.call(tip);

let x = d3.scaleTime().range([0, width]);

let y = d3.scaleLinear().rangeRound([height, 0]);

d3.json("https://raw.githubusercontent.com/FreeCodeCamp/ProjectReferenceData/master/GDP-data.json", function(response) {
  let data = response.data;

  x.domain([new Date(data[0][0]), new Date(data[data.length-1][0])]);
  y.domain([0, d3.max(data, function(d) { return d[1]; })]);

  let barWidth = width / data.length;

  chart.append("g")
      .attr("class", "axis x")
      .attr("transform", "translate(0,"+(height)+")")
      .call(d3.axisBottom(x).ticks(10));

  chart.append("g")
      .attr("class", "axis y")
      .call(d3.axisLeft(y).ticks(10));
  chart.append("text")
      .attr("transform", "rotate(-90)")
      .attr("y", 6)
      .attr("dy", "0.71em")
      .attr("text-anchor", "end")
      .text("Gross Domestic Product, USA");

  //here x is already the x axis time scale you have defined in your code
  var left = x(new Date("Jun 3 1980"));
  var right = x(new Date("Apr 22 2013")); //one more day
  var wid = right - left;
  chart.append("rect")
    .attr("x", left)
    .attr("width", wid)
    .attr('class', 'promo' )
    .attr("height", height);

  let bar = chart.selectAll('.bar')
                  .data(data)
                  .enter();

  bar.append('rect')
     .attr('class', 'price')
     .attr('x', function(d, i) {
        return (i*barWidth);
      })
     .attr('y', function(d) { return y(d[1]); })
     .attr("height", function(d) { return height - y(d[1]); })
     .attr("width", barWidth)
     .on('mouseover', tip.show)
     .on('mouseout', tip.hide);
});

Solutions I've encountered relate to charts with specific pixel sizes, and adding margins to these, so that the axis labels occupy this space. Practically, this approach is not possible with a chart that is sized responsively (100% width and 50% of the viewport height).

What can I do to get my labels to display as required?

1
If you want to see axes, then you need a margin to allow space (they can be relative to the width and height if you make them so). Consider turning off the viewbox resize and write a resize method that updates/redraws everything in response to changes in the container height/width: bl.ocks.org/curran/3a68b0c81991e2e94b19.Ryan Morton
@RyanMorton I'd read about that approach - resizing on container size changes, but I'd also read it was not the recommended approach. Could you possibly formulate your comment into a working example, using this approach?BrynJ
@RyanMorton I've since taken the approach you recommended, but it's not quite working correctly. See this question for all the details.BrynJ

1 Answers

0
votes

I have few observation on the above chart. SVG height and x axis starting from the same position. So the visibility of the axis will hidden because axis tick and text are come out of svg viewbox. You can probably think for transform attribute and position the element properly. JSFiddle

x axis positioning

chart.append("g")
      .attr("class", "axis x")
      .attr("transform", "translate(0,"+(height -20)+")")
      .call(d3.axisBottom(x).ticks(10));

rectangle grouping and positioning

   var bar_g = chart.append("g")
   .attr('class','rectg')
   .attr("transform", "translate(0,"+(-20)+")");