D3 Programmatic rotation of radial Graph

I have a graph that uses d3.radialLine that can be seen in this fiddle. My data points on the line are visualized by plotting the circle on the proper axis value. I need to have a line down the middle of the svg element that will give me the reading of the plotted data point that is touching it. You can see a graphic image of what I'm trying to accomplish:

enter image description here

I would like to programmatically rotate, for example clockwise so that December will be inline with the red line, and be able to read that data point. I know that I'll have to get the x2 value of the red line and use 'x2' of the December value to find out how many degrees I would need to rotate the graph, but I can't seem to figure that part out. The code was taken from Radar Chart.

I know that formula for rotating..d3.select(...).attr('transform', 'rotate(degree, x, y)'


            //////////////////////// Set-Up ////////////////////////////// 

            var margin = {top: 100, right: 100, bottom: 100, left: 100},
                width = Math.min(700, window.innerWidth - 10) - margin.left - margin.right,
                height = Math.min(width, window.innerHeight - margin.top - margin.bottom - 20);

            ////////////////////////// Data ////////////////////////////// 

            var data = [
                      // Yearly
                      [{axis:"Jan",value: 700},
                      {axis:"Feb",value: 1453},
                      {axis:"March",value: 1300},
                      {axis:"April",value: 1534},
                      {axis:"May",value: 1534},
                      {axis:"June",value: 1547},
                      {axis:"July",value: 1100},
                      {axis:"August",value: 1800},
                      {axis:"September",value: 1700},
                      {axis:"October",value: 1500},
                      {axis:"November",value: 1000},
                      {axis:"December",value: 1200}

            //////////////////// Draw the Chart ////////////////////////// 

            var color = d3.scaleOrdinal()

            var radarChartOptions = {
              w: width,
              h: height,
              margin: margin,
              maxValue: 0.5,
              levels: 5,
              roundStrokes: true,
              color: color,
              opacityCircles: 0.1

            //Call function to draw the Radar chart
            RadarChart(".radarChart", data, radarChartOptions);

/////////////// The Radar Chart Function ////////////////
/////////////// Written by Nadieh Bremer ////////////////
////////////////// VisualCinnamon.com ///////////////////
/////////// Inspired by the code of alangrafu ///////////

function RadarChart(id, data, options) {
    var cfg = {
     w: 600,                //Width of the circle
     h: 600,                //Height of the circle
     margin: {top: 20, right: 20, bottom: 20, left: 20}, //The margins of the SVG
     levels: 3,             //How many levels or inner circles should there be drawn
     maxValue: 0,           //What is the value that the biggest circle will represent
     labelFactor: 1.25,     //How much farther than the radius of the outer circle should the labels be placed
     wrapWidth: 60,         //The number of pixels after which a label needs to be given a new line
     opacityArea: 0.35,     //The opacity of the area of the blob
     dotRadius: 4,          //The size of the colored circles of each blog
     opacityCircles: 0.1,   //The opacity of the circles of each blob
     strokeWidth: 2,        //The width of the stroke around each blob
     roundStrokes: false,   //If true the area and stroke will follow a round path (cardinal-closed)
     color: d3.scaleOrdinal(d3.schemeCategory10)    //Color function

    //Put all of the options into a variable called cfg
    if('undefined' !== typeof options){
      for(var i in options){
        if('undefined' !== typeof options[i]){ cfg[i] = options[i]; }
      }//for i

    //If the supplied maxValue is smaller than the actual one, replace by the max in the data
    var maxValue = Math.max(cfg.maxValue, d3.max(data, function(i){return d3.max(i.map(function(o){return o.value;}))}));

    var allAxis = (data[0].map(function(i, j){return i.axis})), //Names of each axis
        total = allAxis.length,                 //The number of different axes
        radius = Math.min(cfg.w/2, cfg.h/2),    //Radius of the outermost circle
        Format = d3.format(''),             //Percentage formatting
        angleSlice = Math.PI * 2 / total;       //The width in radians of each "slice"

    //Scale for the radius
    var rScale = d3.scaleLinear()
        .range([0, radius])
        .domain([0, maxValue]);

    //////////// Create the container SVG and g /////////////

    //Remove whatever chart with the same id/class was present before

    //Initiate the radar chart SVG
    var svg = d3.select(id).append("svg")
            .attr("width",  cfg.w + cfg.margin.left + cfg.margin.right)
            .attr("height", cfg.h + cfg.margin.top + cfg.margin.bottom)
            .attr("class", "radar"+id);
    //Append a g element        
    var g = svg.append("g")
            .attr("transform", "translate(" + (cfg.w/2 + cfg.margin.left) + "," + (cfg.h/2 + cfg.margin.top) + ")");

    ////////// Glow filter for some extra pizzazz ///////////

    //Filter for the outside glow
    var filter = g.append('defs').append('filter').attr('id','glow'),
        feGaussianBlur = filter.append('feGaussianBlur').attr('stdDeviation','2.5').attr('result','coloredBlur'),
        feMerge = filter.append('feMerge'),
        feMergeNode_1 = feMerge.append('feMergeNode').attr('in','coloredBlur'),
        feMergeNode_2 = feMerge.append('feMergeNode').attr('in','SourceGraphic');

    /////////////// Draw the Circular grid //////////////////

    //Wrapper for the grid & axes
    var axisGrid = g.append("g").attr("class", "axisWrapper");

    //Draw the background circles
        .attr("class", "gridCircle")
        .attr("r", function(d, i){return radius/cfg.levels*d;})
        .style("fill", "#CDCDCD")
        .style("stroke", "#CDCDCD")
        .style("fill-opacity", cfg.opacityCircles)
        .style("filter" , "url(#glow)");

    //Text indicating at what % each level is
       .attr("class", "axisLabel")
       .attr("x", 4)
       .attr("y", function(d){return -d*radius/cfg.levels;})
       .attr("dy", "0.4em")
       .style("font-size", "10px")
       .attr("fill", "#737373")
       .text(function(d,i) { return Format(maxValue * d/cfg.levels); });

    //////////////////// Draw the axes //////////////////////

    //Create the straight lines radiating outward from the center
    var axis = axisGrid.selectAll(".axis")
        .attr("class", "axis");
    //Append the lines
        .attr("x1", 0)
        .attr("y1", 0)
        .attr("x2", function(d, i){ return rScale(maxValue*1.1) * Math.cos(angleSlice*i - Math.PI/2); })
        .attr("y2", function(d, i){ return rScale(maxValue*1.1) * Math.sin(angleSlice*i - Math.PI/2); })
        .attr("class", "line")
    .style("stroke", "white")
        .style("stroke-width", "2px");

    //Append the labels at each axis
        .attr("class", "legend")
        .style("font-size", "11px")
        .attr("text-anchor", "middle")
        .attr("dy", "0.35em")
        .attr("x", function(d, i){ return rScale(maxValue * cfg.labelFactor) * Math.cos(angleSlice*i - Math.PI/2); })
        .attr("y", function(d, i){ return rScale(maxValue * cfg.labelFactor) * Math.sin(angleSlice*i - Math.PI/2); })
        .text(function(d){return d})
        .call(wrap, cfg.wrapWidth);

    ///////////// Draw the radar chart blobs ////////////////

    //The radial line function
    var radarLine = d3.radialLine()
        .radius(function(d) { return rScale(d.value); })
        .angle(function(d,i) {  return i*angleSlice; });

    if(cfg.roundStrokes) {

    //Create a wrapper for the blobs    
    var blobWrapper = g.selectAll(".radarWrapper")
        .attr("class", "radarWrapper");

    //Append the backgrounds    
        .attr("class", "radarArea")
        .attr("d", function(d,i) { return radarLine(d); })
        .style("fill", function(d,i) { return cfg.color(i); })
        .style("fill-opacity", cfg.opacityArea)
        .on('mouseover', function (d,i){
            //Dim all blobs
                .style("fill-opacity", 0.1); 
            //Bring back the hovered over blob
                .style("fill-opacity", 0.7);    
        .on('mouseout', function(){
            //Bring back all blobs
                .style("fill-opacity", cfg.opacityArea);

    //Create the outlines   
        .attr("class", "radarStroke")
        .attr("d", function(d,i) { return radarLine(d); })
        .style("stroke-width", cfg.strokeWidth + "px")
        .style("stroke", function(d,i) { return cfg.color(i); })
        .style("fill", "none")
        .style("filter" , "url(#glow)");        

    //Append the circles
        .data(function(d,i) { return d; })
        .attr("class", "radarCircle")
        .attr("r", cfg.dotRadius)
        .attr("cx", function(d,i){ return rScale(d.value) * Math.cos(angleSlice*i - Math.PI/2); })
        .attr("cy", function(d,i){ return rScale(d.value) * Math.sin(angleSlice*i - Math.PI/2); })
        .style("fill", function(d,i,j) { return cfg.color(j); })
        .style("fill-opacity", 0.8);

    //////// Append invisible circles for tooltip ///////////

    //Wrapper for the invisible circles on top
    var blobCircleWrapper = g.selectAll(".radarCircleWrapper")
        .attr("class", "radarCircleWrapper");

    //Append a set of invisible circles on top for the mouseover pop-up
        .data(function(d,i) { return d; })
        .attr("class", "radarInvisibleCircle")
        .attr("r", cfg.dotRadius*1.5)
        .attr("cx", function(d,i){ return rScale(d.value) * Math.cos(angleSlice*i - Math.PI/2); })
        .attr("cy", function(d,i){ return rScale(d.value) * Math.sin(angleSlice*i - Math.PI/2); })
        .style("fill", "none")
        .style("pointer-events", "all")
        .on("mouseover", function(d,i) {
            newX =  parseFloat(d3.select(this).attr('cx')) - 10;
            newY =  parseFloat(d3.select(this).attr('cy')) - 10;

                .attr('x', newX)
                .attr('y', newY)
                .style('opacity', 1);
        .on("mouseout", function(){
                .style("opacity", 0);

    //Set up the small tooltip for when you hover over a circle
    var tooltip = g.append("text")
        .attr("class", "tooltip")
        .style("opacity", 0);

    /////////////////// Helper Function /////////////////////

    //Taken from http://bl.ocks.org/mbostock/7555321
    //Wraps SVG text    
    function wrap(text, width) {
      text.each(function() {
        var text = d3.select(this),
            words = text.text().split(/\s+/).reverse(),
            line = [],
            lineNumber = 0,
            lineHeight = 1.4, // ems
            y = text.attr("y"),
            x = text.attr("x"),
            dy = parseFloat(text.attr("dy")),
            tspan = text.text(null).append("tspan").attr("x", x).attr("y", y).attr("dy", dy + "em");

        while (word = words.pop()) {
          tspan.text(line.join(" "));
          if (tspan.node().getComputedTextLength() > width) {
            tspan.text(line.join(" "));
            line = [word];
            tspan = text.append("tspan").attr("x", x).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word);



For rotating you just need to increase your initial angle offset over time.

Here's an example:


As we know the angle is dependent to the index of the datum, you can calculate the value of the red dots under the red line in this way.

var currentAngle = (offset - Math.PI/2) % (Math.PI*2);
var currentIndex = Math.floor( (currentAngle/(Math.PI*2)) * data[0].length);
var currentValue = data[0][currentIndex].value;