block by timelyportfolio 3177376

d3.js grouped bar with incorrect text rotation

Full Screen

index.html

<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8" />
  <title>d3.js Grouped Bar Chart</title>

  <script  src="//d3js.org/d3.v2.min.js?2.9.1"></script>         <style>
            .axis path, .axis line {
                fill: none;
                stroke: #000;
                shape-rendering: crispEdges;
            }
        </style>
</head>
<body>
<h3>d3.js Axys Chart    <a href="//ramblings.mcpher.com">(thanks so much to ramblings.mcpher.com)</a></h3>
    <br>
        <script>
            var perfdata = new Array();

            var margin = {top: 20, right: 60, bottom: 60, left: 60},
                width = 960 - margin.right - margin.left,
                height = 500 - margin.top - margin.bottom;
            
            var x = d3.time.scale()
                .range([0, width - 60]);
            
            var y = d3.scale.linear()
                .range([height - 20, 0]);
        
            var duration = 1500,
                delay = 500;
            
            var color = d3.scale.category10();
            
            var svg = d3.select("body").append("svg")
                .attr("width", width + margin.right + margin.left)
                .attr("height", height + margin.top + margin.bottom)
                .append("g")
                .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
            
            var parse = d3.time.format("%m/%d/%Y").parse, format = d3.time.format("%Y"),
              perfdata = new Array();   
         </script><script> var data, origdata = {
   "cDataSet":[      {
         "date":"12/31/1991",
         "portfolio":"16.27",
         "sp500":"30.47"
      },
      {
         "date":"12/31/1992",
         "portfolio":"7.99",
         "sp500":"7.62"
      },
      {
         "date":"12/31/1993",
         "portfolio":"6.55",
         "sp500":"10.08"
      },
      {
         "date":"12/31/1994",
         "portfolio":"0.44",
         "sp500":"1.32"
      },
      {
         "date":"12/31/1995",
         "portfolio":"16.08",
         "sp500":"37.58"
      },
      {
         "date":"12/31/1996",
         "portfolio":"11.56",
         "sp500":"22.96"
      },
      {
         "date":"12/31/1997",
         "portfolio":"18.2",
         "sp500":"33.36"
      },
      {
         "date":"12/31/1998",
         "portfolio":"13.98",
         "sp500":"28.58"
      },
      {
         "date":"12/31/1999",
         "portfolio":"9.09",
         "sp500":"21.04"
      },
      {
         "date":"12/31/2000",
         "portfolio":"0.13",
         "sp500":"-9.1"
      },
      {
         "date":"12/31/2001",
         "portfolio":"-4.83",
         "sp500":"-11.89"
      },
      {
         "date":"12/31/2002",
         "portfolio":"-7.81",
         "sp500":"-22.1"
      },
      {
         "date":"12/31/2003",
         "portfolio":"16.2",
         "sp500":"28.68"
      },
      {
         "date":"12/31/2004",
         "portfolio":"7.97",
         "sp500":"10.88"
      },
      {
         "date":"12/31/2005",
         "portfolio":"5.57",
         "sp500":"4.91"
      },
      {
         "date":"12/31/2006",
         "portfolio":"11.69",
         "sp500":"15.79"
      },
      {
         "date":"12/31/2007",
         "portfolio":"6.92",
         "sp500":"5.49"
      },
      {
         "date":"12/31/2008",
         "portfolio":"-25",
         "sp500":"-37"
      },
      {
         "date":"12/31/2009",
         "portfolio":"19.92",
         "sp500":"26.46"
      },
      {
         "date":"12/31/2010",
         "portfolio":"13.59",
         "sp500":"15.06"
      },
      {
         "date":"12/31/2011",
         "portfolio":"-1.58",
         "sp500":"2.11"
      }
    ]
 };</script>        <script>
                var inc = 0;
            
                data = origdata.cDataSet;
                
                var cumul = new Array();
                
                for (key in data[0]) {
                    if ( key != "date" ) {
                        cumul[key] = 1;
                        firstdate = parse(data[0].date);
                        firstdate.setFullYear(firstdate.getFullYear()-1);
                        perfdata[inc]  = { date: firstdate, perf : 0, cumul : cumul[key], symbol : key };
                        inc = inc + 1;
                   }
                }
            
                data.forEach( function(d) {
                    for (key in d) {
                        if ( key != "date" ) {
                            cumul[key] = cumul[key] * (1 + parseFloat(d[key]) / 100);
                            perfdata[inc]  = { date: parse(d.date) , perf : parseFloat(d[key]), cumul : cumul[key], symbol : key };
                            inc = inc + 1;
                        }
                    };
                });
                  
                //if we want to filter only some set of what is there
                //stocks = perfdata.filter(function(d) { return d.symbol in filter; });
                
                // Nest stock values by symbol.
                symbols = d3.nest()
                  .key(function(d) { return d.symbol; })
                  .entries(perfdata);
                
                // Compute the minimum and maximum date across symbols.
                x.domain([
                    d3.min(symbols, function(d) { return d.values[0].date; }),
                    d3.max(symbols, function(d) { return d.values[d.values.length - 1].date; })
                ]);
                
                var g = svg.selectAll("g")
                    .data(symbols)
                    .enter().append("g")
                        .attr("class", "symbol");  
                                
            groupedBar();

            function groupedBar() {
                  x = d3.scale.ordinal()
                      .domain(symbols[0].values.map(function(d) { return d.date; }))
                      .rangeBands([0, width - 60], .1);
                
                  var x1 = d3.scale.ordinal()
                      .domain(symbols.map(function(d) { return d.key; }))
                      .rangeBands([0, x.rangeBand()]);
    
                var y0 = Math.max(Math.abs(d3.min(symbols.map(function(d) { return d3.min(d.values.map(function(d) { return d.perf; })); }))), d3.max(symbols.map(function(d) { return d3.max(d.values.map(function(d) { return d.perf; })); })));                
                y
                    .domain([-y0, y0])
                    //.domain([d3.min(symbols.map(function(d) { return d3.min(d.values.map(function(d) { return d.perf; })); })), d3.max(symbols.map(function(d) { return d3.max(d.values.map(function(d) { return d.perf; })); }))])
                    .range([height, 0])
                    .nice();
                
                var yAxis = d3.svg.axis().scale(y).orient("left");                            

                svg.selectAll(".labels")
                    .data(symbols[0].values.map(function(d) { return d.date; }))
                    .enter().append("text")
                        .attr("class", "labels")
                        .attr("text-anchor", "middle")
                        .attr("x", function(d,i) { return x(i) + x.rangeBand() / 2 ; })
                        .attr("y", height / 2 + 15)
                        .text(function(d) {return format(d) })
                        .style("fill-opacity", 1);

                
                  var g = svg.selectAll(".symbol");
                
                  var t = g.transition()
                      .duration(duration);
                      
                    //got working with lots of help but this section particularly dedicated to //stackoverflow.com/questions/10127402/bar-chart-with-negative-values
                  g.each(function(p, j) {
                    d3.select(this).selectAll("rect")
                        .data(function(d) { return d.values; })
                      .enter().append("rect")
                        .attr("x", function(d) { return x(d.date) + x1(p.key); })
                        .attr("y", function(d, i) { return y(Math.max(0, d.perf)); })                        
                        //.attr("y", function(d) { return y(d.perf); })
                        .attr("width", x1.rangeBand())
                        .attr("height", function(d, i) { return Math.abs(y(d.perf) - y(0)); })                        
                        //.attr("height", function(d) { return height - y(d.perf); })
                        .style("fill", color(p.key))
                        .style("fill-opacity", 1e-6)                    
                        //very grateful to //blog.nextgenetics.net/demo/entry0032/ for help here on mouseover highlighting
                        //another nice example //bl.ocks.org/2164562
                        .on('mouseover', function(d, i) {
                             d3.select(this).style('fill','gray');
                             statusText
                                .text(p.key + " " + d.perf)
                                .attr('fill',color(p.key))
                                .attr("text-anchor", "start")
                                .attr("x", x(d.date) + x1(p.key))
                                .attr("y", y(d.perf))
                                .attr("transform", "rotate(-90 " + x(d.date) + x1(p.key) + "," + y(d.perf) + ")"); 
                          })
                          .on('mouseout', function(d,i) {
                             statusText
                                .text('');
                             d3.select(this).style('fill',color(p.key));
                          })
                          .transition()
                                .duration(duration)
                                .style("fill-opacity", 1);

                    
                  var statusText = svg.append('svg:text');
                      
                  });                                                   
            };            
  </script>
 </body>
</html>