score:2

Accepted answer

It's actually easier than you think. You just need to call the axis functions again:

svg.select("g.x").call(xAxis);
svg.select("g.y").call(yAxis);

Changed jsfiddle here.

To get the labels to work, you can give those text elements a specific class and select accordingly. By default, D3 matches elements based on the index. That is, after you've added the axis labels by calling the axes, those will be selected and matched against the data. Therefore, the .enter() selection will be empty with no new labels added.

Jsfiddle with that as well here.

score:2

For the second part of your question:

The labels weren't showing up properly because you were just using selectAll("text") to grab them. The problem with that is that the tick labels on the axes are text elements, too, so they were getting selected and assigned the data -- but then not included in your "enter". That is also why the axis labels moved off screen when you updated the data (since in that case, you were setting attributes on all elements, not just new ones).

To fix: Add a class to the bar labels, and use it to select them specifically:

svg.selectAll("text.barLabels") //use this selector in your update as well
    .data(data)
    .enter()
    .append("text")
    .classed("barLabels", true) //remember to actually add the class!

It should all work now ...almost.

You could probably figure out this on your own, but your label y-positioning function wasn't taking into consideration the fact that you were using an inverted scale, so the labels all ended up in weird positions. You also need to change

.attr("y", function (d) {
    return height - y(d.max_energy) + 24;
});

to

.attr("y", function (d) { 
    return y(d.max_energy) + 24;
})

or

.attr("y", function (d) { 
    return Math.min(y(d.max_energy) + 24, height);
})

so that "0.0" labels aren't positioned beyond the axis line; or even

.attr("y", function (d,i) { 
    return Math.min(y(d.max_energy) + 24*(1+i%2), height);
})

so that adjacent labels don't overlap if they are too wide for the bar. (The i%2 just returns 0 for even numbers and 1 for odd numbers; the modulo operator % gives back the "remainder" from integer division.)

The last version is what I've got implemented here: http://jsfiddle.net/h8Rsg/40/


Related Query