Subrata Sarkar
Subrata Sarkar

Reputation: 3064

D3 charting tool: Cannot display labels above columns in bar chart

I know it is recommended to create a different question for each but the deadline to too short so I have opted for this option. I am really sorry about this and requesting expert advice.

I am completely new to D3 charting tool. So far I have managed to render the following chart using v4:

wp_enqueue_script( 'd3-chart', 'https://d3js.org/d3.v4.min.js' );

enter image description here

But having a hard time to get the following things to work! I must be doing something wrong but don't know what that is.

Labels above each bar/column
I tried the following code by referring this fiddle, but the labels are never coming up!

svg.selectAll("rect")
   .data(data)
   .enter().append("rect")
   .attr("x", function(d) { return x(d.month); })
   .attr("width", x.bandwidth())
   .attr("y", function(d) { return y(d.points); })
   .attr("height", function(d) { return height - y(d.points); })
   .attr("fill", function(d){return barColor(d.data_month_number, d.current_month_number)});

//set the label
svg.selectAll("text")
   .data(data)
   .enter()
   .append("text")
   .text(function(d) {
      return d.points;
   })
   .attr("text-anchor", "middle")
   .attr("x", function(d, i) {
      return i * (w / data.length) + (w / data.length - barPadding) / 2;
   })
   .attr("y", function(d) {
      return h - (d.points * 4) + 14;
   })
   .attr("font-family", "sans-serif")
      .attr("font-size", "11px")
      .attr("fill", "black");

Controlling Y-Axis tick values
Ideally, the top-most line should be greater than the largest column value, which for me is 23. But it stops at 20. I referred to this tutorial and tried the following. But it is not working.

function make_y_gridlines() {
   return d3.axisLeft(y)
    .ticks(7)
    .tickValues([0, 5, 10, 15, 20, 25, 30]);
}

...

svg.append("g")
  .attr("class", "grid")
  .call(make_y_gridlines()
    .tickSize(-width)
  );

The following JSON I am using for rendering the chart:

[{
    "target_goal": 7, // This is to be used for the additional horizonal line (Target Goal)
    "current_month_number": 11,
    "data_month_number": 4,
    "month": "Apr-19", // Used as X-Axis label and they are coming up correctly
    "points": 3  // Columns are rendering fine but cannot display as labels above each
}, {
    "target_goal": 7,
    "current_month_number": 11,
    "data_month_number": 5,
    "month": "May-19",
    "points": 3
}, {
    "target_goal": 7,
    "current_month_number": 11,
    "data_month_number": 6,
    "month": "Jun-19",
    "points": 5
}, {
    "target_goal": 7,
    "current_month_number": 11,
    "data_month_number": 7,
    "month": "Jul-19",
    "points": 7
}, {
    "target_goal": 7,
    "current_month_number": 11,
    "data_month_number": 8,
    "month": "Aug-19",
    "points": 6
}, {
    "target_goal": 7,
    "current_month_number": 11,
    "data_month_number": 9,
    "month": "Sep-19",
    "points": 4
}, {
    "target_goal": 7,
    "current_month_number": 11,
    "data_month_number": 10,
    "month": "Oct-19",
    "points": 23
}, {
    "target_goal": 7,
    "current_month_number": 11,
    "data_month_number": 11,
    "month": "Nov-19",
    "points": 7
}, {
    "target_goal": 7,
    "current_month_number": 11,
    "data_month_number": 12,
    "month": "Dec-19",
    "points": 7
}]

Edit

The final chart needs to look like this.

enter image description here

UPDATE (Nov 27)

Inspection result of my chart. No <text> is rendered!

enter image description here

Inspection result of the Fiddle chart

enter image description here

Upvotes: 1

Views: 156

Answers (2)

Tim Hirst
Tim Hirst

Reputation: 614

Without your full code it's a little hard to diagnose for sure what's going on, but one golden rule for finding out yourself, and a couple of things to think about and try:

Golden Rule

Check what's actually happening in the DOM (Check out https://developers.google.com/web/tools/chrome-devtools/dom in case you're not sure what I mean by that) Have the labels been added to your <svg> and just not in the right place, in which case where are they, and what went wrong in that calculation? Or are they missing altogether, in which case was there something wrong with your selection or the data you tried to bind to it?

Things to try from eyeballing your code

  • When you're selecting text elements to bind data points to (i.e. svg.selectAll("text")) this will bind your data to any existing <text> elements in the document, so if this comes after, say, adding your axes you might get some very strange selections that you end up unintentionally modifying. I would instead do something like this so that it only applies to the labels you are trying to add:
svg.selectAll(".data-labels")
    .data(data)
    .enter()
    .append("text")
    .attr("class","data-labels")
    .text(function(d) {
        return d.points;
     })
  • Your function for the y position,return h - (d.points * 4) + 14; smells a bit odd - remember this is the y position on the page rather than the y value of the data, so it just feels a bit odd that you don't use y(d.points) anywhere in it. I'd also be suprised if you wanted to add an offset rather than subtract (remeber that y is measured from the top, not the bottom!) Did you mean it to be return h - y(d.points) - 14;? Maybe they are there, but styled so you can't see them?

Hope at least some of that helps!

Upvotes: 1

Saket
Saket

Reputation: 36

I made a small change in displaying text.

as below

//set the label
svg.selectAll("text")
  .data(dataset)
  .enter()
  .append("text")
  .text(function(d) {
    return d;
  })
  .attr("text-anchor", "middle")
  .attr("x", function(d, i) {
    return i * (w / dataset.length) + (w / dataset.length - barPadding) / 2;
  })
  .attr("y", function(d) {
    return h - (d * 4)-5;
  })
  .attr("font-family", "sans-serif")
  .attr("font-size", "11px")
  .attr("fill", "red");

we need to subtract from height to go up in d3. working fiddle is here fiddle

Upvotes: 0

Related Questions