2016-10-17 205 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