2016-10-17 201 views
2

嗨,我是D3新手,我試圖將標準化堆積條形圖轉換爲堆積條形圖。我有共同的下拉菜單在兩個圖表(標準化堆積條形圖和堆積條形圖)之間切換。在標準化堆積條形圖和堆積條形圖之間切換簡單嗎?還是需要進行重大更改?我爲此創建了plunker標準化堆積條形圖到堆積條形圖

var svg = d3.select("svg"), 
    margin = { 
     top: 20, 
     right: 60, 
     bottom: 30, 
     left: 40 
    }, 
    width = +svg.attr("width") - margin.left - margin.right, 
    height = +svg.attr("height") - margin.top - margin.bottom, 
    g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

    var y = d3.scaleBand() 
    .rangeRound([0, width]) 
    .padding(0.1) 
    .align(0.1); 

    var x = d3.scaleLinear() 
    .rangeRound([height, 0]); 

    var z = d3.scaleOrdinal() 
    .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", '#02CA22','#FB5652','#FFB005']); 

    var stack = d3.stack() 
    .offset(d3.stackOffsetExpand); 

    d3.csv("data.csv", type, function(error, data) { 
    if (error) throw error; 

    data.sort(function(a, b) { 
     return b[data.columns[1]]/b.total - a[data.columns[1]]/a.total; 
    }); 

    y.domain(data.map(function(d) { 
     return d.State; 
    })); 
    z.domain(data.columns.slice(1)); 

    var serie = g.selectAll(".serie") 
     .data(stack.keys(data.columns.slice(1))(data)) 
     .enter().append("g") 
     .attr("class", "serie") 
     .attr("fill", function(d) { 
     return z(d.key); 
     }); 

    serie.selectAll("rect") 
     .data(function(d) { 
     return d; 
     }) 
     .enter().append("rect") 
     .attr("y", function(d) { 
     return y(d.data.State); 
     }) 
     .attr("x", function(d) { 
     return x(d[1]); 
     }) 
     .attr("width", function(d) { 
     return x(d[0]) - x(d[1]); 
     }) 
     .attr("height", y.bandwidth()); 

    g.append("g") 
     .attr("class", "axis axis--x") 
     .attr("transform", "translate(0," + height + ")") 
     .call(d3.axisBottom(x).ticks(10, "%")); 

    g.append("g") 
     .attr("class", "axis axis--y") 
     .call(d3.axisLeft(y)); 

    var legend = serie.append("g") 
     .attr("class", "legend") 
     .attr("transform", function(d) { 
     var d = d[0]; 
     return "translate(" + ((x(d[0]) + x(d[1]))/2) + ", " +(y(d.data.State) - y.bandwidth())+ ")"; 
     }); 

    legend.append("line") 
     .attr("y1", 5) 
     .attr("x1", 15) 
     .attr("x2", 15) 
     .attr("y2", 12) 
     .attr("stroke", "#000"); 

    legend.append("text") 
     .attr("x", 9) 
     .attr("dy", "0.35em") 
     .attr("fill", "#000") 
     .style("font", "10px sans-serif") 
     .text(function(d) { 
     return d.key; 
     }); 
    }); 

    function type(d, i, columns) { 
    for (i = 1, t = 0; i < columns.length; ++i) t += d[columns[i]] = +d[columns[i]]; 
    d.total = t; 
    return d; 
    } 

回答

3

不,這並不簡單。您必須進行六次更改(就像將水平條形圖更改爲垂直條形圖一樣)。

這是必要的修改列表:

  1. 刪除.offset(d3.stackOffsetExpand)。根據API:

適用零基線和歸一化的值對於每個點,使得背線總是一個。

所以,你的堆棧功能應該是:

var stack = d3.stack() 
    .offset(d3.stackOffsetNone); 

或者你可以簡單地丟棄.offset

  • 更改從這個排序:

    data.sort(function(a, b) { 
        return b[data.columns[1]]/b.total - a[data.columns[1]]/a.total; 
    }); 
    
  • 向該:

    data.sort(function(a, b) { return b.total - a.total; }); 
    
  • 設置x比例的域:

    x.domain([0, d3.max(data, function(d) { return d.total; })]).nice(); 
    
  • 反轉的X標尺的範圍:

    var x = d3.scaleLinear() 
        .rangeRound([0, width]); 
    
  • 更改x和rects的width

    .attr("x", function(d) { 
        return x(d[0]); 
    }) 
    .attr("width", function(d) { 
        return x(d[1]) - x(d[0]); 
    }) 
    
  • 這裏是plunkr:http://plnkr.co/edit/Sa3FqmYk5KkQRnSNM2Wf?p=preview