D3 - X Axis labels are overlapping - javascript

I'm create a line chart using D3 v4 and the labels X are overlapping.
// Add the X Axis
var xAxis = svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x)
.tickValues(data.map(d=>d.date))
.tickFormat(d3.timeFormat("%d/%m %H:%M")))
.selectAll("text")
.attr("transform", "rotate(90)")
.attr("dy", ".35em")
.attr("y", 0)
.attr("x", 9)
.style("text-anchor", "start");
The full code is here: JSFiddle

Do not use given tick values. The data points near the right end of the chart are too close to each other for doing this. Just remove this line
.tickValues(data.map(d=>d.date))
Show the exact times in a tooltip if they are important.

Related

In d3, how do I include text and a background box as I roll over my line chart?

I'm using d3 v4. I want to display some text corresponding to where folks are mousing-over my line chart and I would like to have a background box on this text. So I'm trying this
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Value");
svg.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line);
var focus = svg.append("g")
.attr("class", "focus")
.style("display", "none");
focus.append("circle")
.attr("r", 4.5);
var rect = focus.append("rect")
.attr("x", 9)
.attr("dy", ".35em")
.attr("width", 50)
.attr("height", 50)
.attr("fill", "yellow");
...
function mousemove() {
var x0 = x.invert(d3.mouse(this)[0]),
i = bisectDate(data, x0, 1),
d0 = data[i - 1],
d1 = data[i],
d = x0 - d0.date > d1.date - x0 ? d1 : d0;
focus.attr("transform", "translate(" + x(d.index_date) + "," + y(d.value) + ")");
rect.select("text").text(formatCurrency(d.value));
}
but what is happening instead is there is just a rectangle without any text floating over my mouseover point as you can see here -- https://jsfiddle.net/xx77tzn3/9/. How do I adjust what I have to include the text and a background box?
<svg>'s (rather unintuitively) don't allow you to append text elements to rect elements. Uncomment
//var text = focus.append("text")
and comment out:
var text = rect.append("text")
Then it the mouse function, change line 113 to this:
focus.select("text").text(formatCurrency(d.value));
Then it's just a matter of formatting the text on that <g>.
EDIT: in order to format the text to be on the rect, you need to make the coordinates of the text relative to the <g>, not the rect. I.e.:
var text = focus.append("text")
//var text = rect.append("text")
.attr("x", 10)
.attr("y", 10);
Now the text is there, and on top of the rectangle.
Updated js.fiddle

D3 show values as label on right axis

I am doing a dot plot in D3 and I want to add the values along a right Y axis. I have done this before in many charts, adding labels is straightforward, but for some reason this particular chart is giving a lot of problems.
I cant get the values of the dots to show on the right axis.
jsfiddle:
The chart appears on click.
The relevant code for the value labels attached to the right axis:
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + (width + 10) + " ,0)")
.call(yAxis1)
.selectAll('text')
.text(function(d){ return xScale(d.value); });
With an ordinal axis you are binding your domain values to the axis ticks. So, the scale domain should be:
var yScale1 = d3.scale.ordinal()
.domain(data.map(function(d) { return d.value; })) //<-- use '.value'
.rangeRoundPoints([0, height]);
Then your y-axis call just becomes:
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + (width + 10) + " ,0)")
.call(yAxis1);
Updated fiddle.

selectAll("g").data(data).enter().append("g") does not work?

For some reason,
chart.selectAll("g").data(data).enter().append("g")
does not work, but
chart.selectAll("rect").data(data).enter().append("rect")
does work. By "work", I mean the element represented by chart finally contains many "rect"/"g, one for each data item. The second line causes the element to finally contain many rect, but nothing will appear if g is used. Any ideas why a simple change from rect to g will cause a bug?
Code:
var chart = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// setup chart axis.
chart.append("g")
.attr("class", "x axis")
.call(xAxis);
chart.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text(yLabel);
// Pertinent code here
var rows = chart.selectAll("g").data(data).enter().append("g");
not sure what you want, but:
if you want something like:
svn
g //one g for every data row
g //y axis
g //x axis
then something like this should work:
var chart = svg
var chartLines = chart
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.attr("class", "line");
// setup chart axis.
chart.append("g")
.attr("class", "x axis")
.call(xAxis);
chart.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text(yLabel);
// Pertinent code here
var rows = chart.selectAll(".line").data(data).enter().append("g");
This is because there are a lot of g elements on the page already when you run this code -- some of them added by you, some of them added by D3 when you call the axis component. There are however no rect elements, so that code works.
There are several ways around this -- you can either run the code that binds the data to the g elements first, add axis and chart in separate g elements, add a class to the g elements that you're binding the data to, or any combination of these.
Some more background and examples in this tutorial.

How to rotate X-axis labels onto the bar in bar chart?

I need to align x-axis labels as shown in the snapshot below:
I tried:
.attr("transform", function(d) {
return "rotate(-90)"
})
But it rotated the whole axis/scale.
How do I fix this?
jsFiddle
EDIT:
I updated my code:
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "0em")
.attr("dy", "0em")
.attr("transform", function(d) {
return "rotate(-90)"
});
Now the labels are rotated to -90 degrees. How do I get it onto the bars?
jsFiddle
You need to rotate only text, and then translate it properly. See the updated fiddle:
svg.selectAll('.tick')
.select('text')
.attr('transform', 'rotate(-90) translate(50, -12)');
http://jsfiddle.net/MjFgK/18/
I'm not that good in using translate. But this fiddle just works fine.
Reason why the whole axis/scale got rotated is because when the text being created with x and y position, the origin point of it becomes (0,0).
So to rotate your text labels you need to position those text using translate instead of x and y.
In the fiddle I've added the below code at the bottom where it text labels are being rotated.
If you wanted to rotate it more. You can just change the degree of rotation.
svg.selectAll(".text")
.data(data)
.enter()
.append("text")
.attr("transform", function(d, i) {
return "translate(" + (35 + x(d.age)) + ", 250)" + "rotate(-90)"
})
.text(function(d) { return d.age; })
Hope this helps for you.

Line not following x os correctly & first tick isn't being shown

See: http://jsfiddle.net/bQHjj/
Following the green line, the circles should be vertically aligned with my x axis, but all of them are moved a few pixels to the right.
The X axis isn't showing it's first tick, which should be 01.05.2013.
My x axis settings:
var xAxis = d3.svg.axis().scale(x).ticks(d3.time.days, 1).tickFormat(d3.time.format("%d.%m.%Y"));
graph.append("svg:g")
.attr("class", "x axis")
.attr("transform", "translate(0," + h + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", function (d) {
return "rotate(-65)"
});
Can anybody tell me what's wrong?
Your date parsing function is not correct, it seems to mess up time zones, since new Date(string) apparently assumes UTC.
This will work:
var format = d3.time.format("%Y-%m-%d");
function getDate(d) {
return format.parse(d.date);
}
cf the updated fiddle.

Categories