2014-02-06 53 views
0

我在svg中添加線條圖時出現問題,部分原因是我認爲是因爲我的x軸使用了月份作爲字符串。即使我沒有標準日期,我也想知道是否有辦法整合這條線。當x軸爲字符串時,在d3.js中堆疊條形圖上的線條圖

 function barStack(d) { 
      var l = d[0].length 
      while (l--) { 
       var posBase = 0, negBase = 0; 
       d.forEach(function(d) { 
        d=d[l] 
        d.size = Math.abs(d.y) 
        if (d.y<0) { 
         d.y0 = negBase 
         negBase-=d.size 
        } else 
        { 
         d.y0 = posBase = posBase + d.size 
        } 
       }) 
      } 
      d.extent= d3.extent(d3.merge(d3.merge(d.map(function(e) { return e.map(function(f) { return [f.y0,f.y0-f.size]})})))) 
      return d 
     } 
     //assets and debts 
     var data = [[{y:3000},{y:2000},{y:2500},{y:1000},{y:3000},{y:5000}], 
        [{y:-700},{y:-300},{y:-1000},{y:-500},{y:-1100},{y:-2000}]] 
     //debt to assets 
     var ratio = [] 
     for (var i = 0; i<data[0].length; i++){ 
      ratio.push(data[1][i]/data[0][i]*-1); 
     } 
     Date.prototype.monthNames = [ 
      "January", "February", "March", 
      "April", "May", "June", 
      "July", "August", "September", 
      "October", "November", "December"]; 
     Date.prototype.getMonthName = function() { 
      return this.monthNames[this.getMonth()]; 
     }; 
     // creates array of previous 6 months 
     var d = new Date(); 
     var n = d.getMonth(); 
     var last_6_months = []; 
     for(var i=data[0].length; i>0; i--){ 
      temp_month = d; 
      temp_month.setMonth(n - i); 
      last_6_months.push(temp_month.getMonthName()); 
     } 
     //combine ratio and dates to use in svg line 
     var data1 = [] 
     for(var i=0; i<data[0].length; i++){ 
      var object = {} 
      object.month = last_6_months[i] 
      object.ratio = ratio[i] 
      data1.push(object) 
     } 
     var h=500 
     ,w=500 
     ,margin=40 
     ,color = d3.scale.category10() 

     ,x = d3.scale.ordinal() 
      .domain(last_6_months) 
      .rangeRoundBands([margin,w-margin], .1) 

     ,y = d3.scale.linear() 
      .range([h-margin,0+margin]) 


     ,xAxis = d3.svg.axis().scale(x).orient("bottom").tickSize(6, 0) 
     ,yAxis = d3.svg.axis().scale(y).orient("left") 

     //variables used in line graph 
     ,y1 = d3.scale.linear() 
       .range([h-margin,0+margin]) 
     ,yAxisRight = d3.svg.axis().scale(y1).orient("right"); 
     ,valueline = d3.svg.line() 
         .x(function(d) { return x(d.month); }) 
         .y(function(d) { return y1(d.ratio); }) 
         .interpolate("linear"); 
     y1.domain(ratio.extent)    


     barStack(data) 
     y.domain(data.extent) 
     svg = d3.select("body") 
       .append("svg") 
       .attr("height",h) 
       .attr("width",w) 

     svg.selectAll(".series").data(data) 
      .enter().append("g").classed("series",true).style("fill", function(d,i) { return color(i)}) 
      .selectAll("rect").data(Object) 
      .enter().append("rect") 
      .attr("x",function(d,i) { return x(x.domain()[i])}) 
      .attr("y",function(d) { return y(d.y0)}) 
      .attr("height",function(d) { return y(0)-y(d.size)}) 
      .attr("width",x.rangeBand()) 

     //line ratio 
     svg.data(data1).enter().append("path") 
      .attr("class", "line") 
      .attr("d", valueline(data1)); 

     svg.append("g").attr("class","axis x").attr("transform","translate (0 "+y(0)+")").call(xAxis) 
     svg.append("g").attr("class","axis y").attr("transform","translate ("+x(margin)+" 0)").call(yAxis) 

     //axis for ratio 
     svg.append("g").attr("class", "axis y").attr("transform", "translate(" + x(margin) + " 0)").style("fill", "red").call(yAxisRight); 

回答

1

d3.svg.line功能沒有問題處理順序規模。但是,通常情況下,您只需要一行的點數就可以使用ordinal.rangePoints()方法。這樣,線上的點將與軸上的點匹配。

由於您使用的是ordinal.rangeBands()來定位條形圖,因此需要指定您希望該線的點位於條的中間。你可以做的是,在d3.svg.line對象的X-存取功能:

valueline = d3.svg.line() 
       .x(function(d) { return x(d.month) + x.rangeBand()/2; }) 
       .y(function(d) { return y1(d.ratio); }) 
       .interpolate("linear"); 

如果你仍然有問題,試圖把一個簡化的工作實例,或者至少職位的問題更具體的細節。