0

I'm trying to create a graph that updates as new values are coming in. In order for the labels on the X axis to be readable I decided to rotate them slightly, so they don't overlap.

When there's a new value, it's being drawn in the graph, then the path (actually the container ) is translated to the left in a transition.

This is how i create the rotated axis labels:

    svg.select(".x.axis")
        .call(this.xAxis)
        .selectAll("text")
            .style("text-anchor", "end")
            .attr("dx", "-.8em")
            .attr("dy", ".15em")
            .attr("transform", this.axislabelrotation);

this.axislabelrotation is:

function(d) {
    return "rotate(-35)" 
}

And this is how i transition the X axis:

    svg = svg.transition().duration(750);
    svg.select(".x.axis") // change the x axis
        .call(this.xAxis)
        .selectAll("text")
            .style("text-anchor", "end")
            .attr("dx", "-.8em")
            .attr("dy", ".15em")
            .attr("transform", this.axislabelrotation);

Though now I have two issues:

  1. At the beginning of the transition the X axis labels jump down a few pixels, during the transition they go back up.
  2. Newly entered labels ("2015" in the example) are not rotated at the beginning of the transition, though rotate to the desired state during the transition.

Example: http://jsfiddle.net/esy6wk8n/2/

fholzer
  • 340
  • 3
  • 13
  • 1
    Hmm, the problem is that the D3 axis doesn't rotate the labels. You could try a custom tween where you rotate the labels at each step. – Lars Kotthoff Feb 24 '15 at 16:36
  • ... or maybe copy+paste and modify the `d3.svg.axis()` source code to create your own custom axis. – meetamit Feb 24 '15 at 18:23

1 Answers1

1

I'd suggest that you remove the transition on the dy and transform attribute.

This updated fiddle may help you with that: http://jsfiddle.net/esy6wk8n/4/

The changes are all in your update function.

    var no_trans = svg;
    svg = svg.transition().duration(750);

    lp.transition()
        .duration(750)
        .attr("transform", "translate(" + this.x(data[0].jdate) + ")");

    lu.transition()
        .duration(750)
        .attr("transform", "translate(" + this.x(data[0].jdate) + ")");

    svg.select(".x.axis") // change the x axis
        .call(this.xAxis)
        .selectAll("text")
            .style("text-anchor", "end")
            .attr("dx", "-.8em");
            //.attr("dy", ".15em")
            //.attr("transform", this.axislabelrotation);

    no_trans.select(".x.axis")
        .selectAll("text")
            .attr("dy", ".15em")
            .attr("transform", this.axislabelrotation);

Basically, I have moved the update of the dy and transform attributes out of the transition, so therefore these values will be set straight away and not be changed as part of the transition, keeping the dy and the transform stable throughout the transition.

Ben Lyall
  • 1,976
  • 1
  • 12
  • 14
  • wow. I didn't know that you could change the axis outside of the transition after you tell d3 to draw it inside a transition. *And* that d3 would then take these changes into account for the transition... – fholzer Feb 25 '15 at 14:54
  • All this is basically doing is setting the `dy` and `transform` attribute immediately, rather than letting the transition interpolate it over time. There's not really anything special going on here. It would be no different to add the elements, set the `dy` and `transform` and then transition the other attributes, the order is not really important, this was just the easiest way to do it with minimal code impact. – Ben Lyall Feb 25 '15 at 21:15