Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

d3 - Rotate x-axis labels

I'm trying this graph:

enter image description here

with my data.

I wanted to rotate the x-axis labels.

Here's the code :

var timeLabels = svg.selectAll(".timeLabel")
          .data(times)
          .enter().append("text")
            .text(function(d) { return d; })
            .attr("x", function(d, i) { return i * gridSize; })
            .attr("y", 0)
            .style("text-anchor", "end")
            .attr("transform", "translate(" + gridSize / 2 + ", -6)rotate(-90)")
            .attr("class", function(d, i) { return ((i >= 8 && i <= 16) ? "timeLabel mono axis axis-worktime" : "timeLabel mono axis"); });

But the result I get is. Entire labels get rotated to -90 deg in a single straight line. Instead I wanted each label to be rotated to -90 deg. Like this:

enter image description here

I even tried using .attr("transform", function(d) {return "translate(" + gridSize / 2 + ", -6)rotate(-90)"}) but it didn't help.

Result :

enter image description here

Help will be very much pleased.

like image 335
user3206082 Avatar asked Jan 17 '14 13:01

user3206082


1 Answers

The problem is that when you rotate an element, it gets rotated around the origin point, (0,0), of the local coordinate system. If the element you're rotating isn't right next to the origin, it can end up moved quite a large distance, and possibly moved outside the chart altogether.

There are two ways you can fix it:

  1. Position the label with a "transform" attribute instead of with x and y attributes. That way, the label's coordinate system -- including the (0,0) point of rotation -- will be positioned with it, and the rotation will happen where you expect. The code @Manoj gave follows that system, but assumes you are using the default xAxis function. For your custom axis label code, your labels are given a y value of 0, and an x value determined from a function. You just need to move those values into the transform attribute, paying careful attention that the transformation of the overall position comes before the rotation and adjustment:

    var timeLabels = svg.selectAll(".timeLabel")
      .data(times)
      .enter().append("text")
        .text(function(d) { return d; })
        .attr("transform", function(d, i) { 
              return "translate(" + ( i * gridSize) + ",0)"
                      + "translate(" + gridSize / 2 + ", -6)rotate(-90)";
         } )
        .style("text-anchor", "end")
        .attr("class", function(d, i) { return ((i >= 8 && i <= 16) ? 
                                   "timeLabel mono axis axis-worktime" : 
                                   "timeLabel mono axis"); 
         });
    

    Of course, you could combine those two translation statements, as:

        .attr("transform", function(d, i) { 
              return "translate(" + ( (i + 0.5) * gridSize) + ",-6)"
                      + "rotate(-90)")
    
  2. Alternately, you can specify a center of rotation in the rotate statement, by including the x and y values of the point you want it to rotate around:

    var timeLabels = svg.selectAll(".timeLabel")
      .data(times)
      .enter().append("text")
        .text(function(d) { return d; })
        .attr("x", function(d, i) { return i * gridSize; })
        .attr("y", 0)
        .attr("transform", function(d, i) { 
              return "translate(" + gridSize / 2 + ", -6)" +
                     "rotate(-90 "+ ((i + 0.5) * gridSize) + " " + (-6) +")";
         } )
        .style("text-anchor", "end")
        .attr("class", function(d, i) { return ((i >= 8 && i <= 16) ? 
                                   "timeLabel mono axis axis-worktime" : 
                                   "timeLabel mono axis"); 
         });
    

    As you can see, this version is rather repetitive, as we have to calculate the position of the label twice -- once to position it, and once to set the center of rotation. You can see why most examples (and the d3 axis functions) position the labels with translations, so they can just be rotated in place.

like image 144
AmeliaBR Avatar answered Nov 16 '22 22:11

AmeliaBR