Curious-Developer
Curious-Developer

Reputation: 33

D3 JS bar chart, show y-axis label value at the top of the bar

I am using Angular 7 and D3JS V4 to implement the bar graph, i need to show the y-axis label value on the top of the bar, i have tried multiple scenarios but failed to do so please help me out to do so..thanx in advance.

 //Initialize SVG
    this.svg = d3.select("#bar-chart");

    this.width = +this.svg.attr("width") - this.margin.left - this.margin.right;
    this.height =
      +this.svg.attr("height") - this.margin.top - this.margin.bottom;
    this.g = this.svg
      .append("g")
      .attr(
        "transform",
        "translate(" + this.margin.left + "," + this.margin.top + ")"
      );

    //Initialize Axis
    this.x = d3Scale
      .scaleBand()
      .rangeRound([0, this.width])
      .padding(0.9);
    this.y = d3Scale.scaleLinear().rangeRound([this.height, 0]);
    this.x.domain(this.totalStores.map(d => d.store));
    this.y.domain([0, d3Array.max(this.totalStores.map(d => d.storeCount))]);

    //Draw Axis
    this.g
      .append("g")

      .attr("transform", "translate(0," + this.height + ")")
      .call(d3Axis.axisBottom(this.x));
    this.g
      .append("g")

      .call(d3Axis.axisLeft(this.y).ticks(4))
      .append("text");

    //Draw Bars
    this.g
      .selectAll(".bar")
      .data(this.totalStores)
      .enter()
      .append("rect")
      .attr("class", "bar")
      .attr("x", d => this.x(d.store))
      .attr("y", d => this.y(d.storeCount))
      .attr("width", this.x.bandwidth())
      .attr("height", d => this.height - this.y(d.storeCount));


jsFiddle

Upvotes: 0

Views: 1741

Answers (2)

Curious-Developer
Curious-Developer

Reputation: 33

Just need to pass the x and y value to text

// Get the y axis value on top
this.g
        .selectAll("text.bar")
        .data(this.totalStores)
        .enter()
        .append("text")
        .attr("class", "yAxis-label")
        .attr("text-anchor", "middle")
        .attr("fill", "#70747a")
        .attr("x", d => this.x(d.store))
        .attr("y", d => this.y(d.storeCount) - 5)
        .text(d => d.storeCount);

Upvotes: 1

Ruben Helsloot
Ruben Helsloot

Reputation: 13129

I draw my y-axes like this:

  drawYAxis(g: d3.Selection<SVGElement, {}, null, undefined> = this.yAxis) {
    g.selectAll(".label").remove();
    return g.call(
            d3.axisLeft(this.y)
              .ticks(getTickFrequency(this.axes[1].format, this.y.domain()))
              .tickSizeInner(this.x.range()[0] - this.x.range()[1])
              .tickSizeOuter(0)
              .tickFormat(Formatter.short(this.axes[1].format)))
        .call(g => g.select(".tick:last-of-type text")
              .clone()
              .classed("label", true)
              .attr("x", 5 - this.margin.left)
              .text(this.axes[1].label));
  }

So I draw my y-axes like you do, using d3.axisLeft with some additional options, then I select the text attached to the last <g> with class tick, and copy the element with its styles, etc. I then move it a little bit to the left, give it a different class, and set the text to a predefined label.

Something like this should work. Keep in mind that you can add different classes and change the positioning to better suit your needs

this.g
    .append("g")
    .call(d3Axis.axisLeft(this.y).ticks(4))
    .select(".tick:last-of-type")
    .append("text")
    .text("My axis label");

Upvotes: 0

Related Questions