I have a d3.js bar chart that is okay for the most part. I want my Y axes label to become horizontal as the text is pretty big, so I am trying to rotate it by 180 degree which makes the text inverted.
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", "-.55em")
.attr("transform", "rotate(-65)"); //works fine
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-180)") //rotated by 180 and text gets inverted
.attr("y", 5)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("avg_facebook_usage_rank");
Here is the fiddle
Related
I'm new to this d3.js. Here I'm trying to draw a bar chart using the d3.v3.js library. Here I'm facing few problems. I have tried to include measure labels onto the y-axis. But once I transform the labels -90 degree its position is automatically changing.
Here's the code I'm used to drawing:
svg.append("g")
.attr("id","x_axis")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", "rotate(-65)");
// .attr("transform", "translate(" + bandSize + ", 0)")
svg.append("g")
.attr("class", "x axis")
.attr("id","dimLabel")
.append("text")
.style("text-anchor", "end")
.attr("x", width/2)
.attr("y", height+55)
.text(dimensionLabels[0]);
svg.append("g")
.attr("id","y_axis1")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("class", "label")
//.attr("transform", "rotate(-90)")
.attr("y", function(d){return y(d3.max(data, function(d) { return d.Metric1; }));});
//Measure Labels
svg.append("g")
.attr("class", "y axis")
.attr("id","measureLabels")
.append("text")
.style("text-anchor", "end")
.attr("x", 0)
.attr("y", height/2)
.text(measureLabels[0]+", "+measureLabels[1])
.attr("transform", "rotate(-90)");
Output Image:
Any help is greatly appreciated.
What you see right now is the expected result, because the rotate function of the transform attribute rotates the element around the origin (0,0), not around its center.
The easiest solution is dropping your attr("x") and attr("y") and positioning the text using the same transform:
var width = 300,
height = 300;
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height);
var text = svg.append("text")
.text("Sum (sales), Sum (quantity)")
.attr("text-anchor", "middle")
.attr("transform", "translate(20," + (height / 2) + ") rotate(-90)")
svg {
border: 1px solid gray;
}
<script src="https://d3js.org/d3.v3.min.js"></script>
Another solution is setting the center of the rotate to the same x and y values:
var width = 300,
height = 300;
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height);
var text = svg.append("text")
.text("Sum (sales), Sum (quantity)")
.attr("text-anchor", "middle")
.attr("x", 20)
.attr("y", 150)
.attr("transform", "rotate(-90, 20, 150)")
svg {
border: 1px solid gray;
}
<script src="https://d3js.org/d3.v3.min.js"></script>
I think you are looking for the css property transform-origin
https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin
I'm trying to rotate x-axis text with the code below :
focus.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.attr("class", "x-axistext")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("font-family", textfontfamily)
.attr("font-weight",textfontweight)
.attr("font-size", textfontsize)
.attr("transform", function (d) {
return "rotate(-65)"
});
Texts are rotating but only when the graph is not zooming. On zooming graph, texts are not rotating. Once you start zooming graph, new texts will be not in rotate position.
Next Problem i'm facing is related to the DateTime Format. Below line of code i'm using to format the text.
var parseDate = d3.timeParse("%H:%M:%S");
But it is also not working properly. Time are showing along with 'AM' 'PM'.
JSFiddle: Here is the complete code
Problem 1
Time are showing along with 'AM' 'PM'.
If you want the time on the ticks to come in a format please provide timeFormat:
xAxis = d3.axisBottom(x).tickFormat(d3.timeFormat("%H:%M:%S"))
Problem 2
On zooming graph, texts are not rotating
On zoom/brush you need to select all ticks and give rotation.
focus.selectAll(".axis--x")
.selectAll("text")
.attr("class", "x-axistext")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("font-family", textfontfamily)
.attr("font-weight",textfontweight)
.attr("font-size", textfontsize)
.attr("transform", function (d) {
return "rotate(-65)"
});
working code here
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.
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.
I have this code for building X & Y axis:
var y = d3.scale.linear()
.range([height*2, 0]);
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
y.domain([-arr2, arr2]).nice();
var x = d3.time.scale().domain([minD, maxD]).range([0, width]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.tickFormat(d3.time.format('%b %y'));
xAxis.ticks(d3.time.year, 1)
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("class", "label")
.attr("x", width + 230)
.attr("y", 10)
.style("text-anchor", "end")
.attr("font-family", "sans-serif")
.attr("font-size", "30px")
.text("Revision Date");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("class", "label")
.attr("transform", "rotate(-90)")
.attr("x", 130)
.attr("y", -10)
.attr("dy", ".71em")
.style("text-anchor", "end")
.attr("font-family", "sans-serif")
.attr("font-size", "30px")
.text("log(Lev)");
Additionally, i have this code creating the circles:
var ARdot = svg.selectAll(".dot")
.data(ArticleData)
.enter().append("circle")
.attr("class", "dot")
.attr("r", 12)
.attr("cx", function(d) { return x(new Date(d.Rev_Date)); })
.attr("cy", function(d) { return y(d.Log_Lev); })
.style("fill", function(d) { return "SteelBlue";});
var TRdot = svg.selectAll(".dot2")
.data(TalkpageData)
.enter().append("circle")
.attr("class", "dot")
.attr("r", 12)
.attr("cx", function(d) { return x(new Date(d.Rev_Date)); })
.attr("cy", function(d) { return y(-d.Log_Lev); })
.style("fill", function(d) { return "LightSeaGreen";});
The result (with the code creating the lines of course) is:
As you can see, blue dots too dense.
I wont to add a zoom in intraction so the user can
zoom in to some part of the graph and the circles and
the X axis's values and Y axis's values behave according the zoom in.
For example: the closer you get to it, in terms of X axis becomes smaller range for the months of the year and in terms of circles, the distances between them gets bigger.