2015-06-29 76 views
1

我有一个堆叠条形图,在每个堆栈中都有标签。现在我想在图表中每个栏的顶部添加另一个标签。我无法在酒吧的顶部放置一个标签,也得到了图表中所有值的总和,因为我想为每个酒吧添加总和。 这里是我的代码,d3中堆叠条形图的所有堆栈的总和

var groups = svg.selectAll("g.cost") 
    .data(dataset.reverse()) 
    .enter().append("g") 
    .attr("class", "cost") 
    .style("fill", function (d, i) { return colors[i]; }); 
var sum = [0]; 

var svg = d3.select("svg"); 
var bar = groups.selectAll("g") 
    .data(function (d) { return d; }) 
.enter().append("g") 
    .attr("transform", function (d, i) { return "translate(0," + i * y(d.y0) - y(d.y0 + d.y) + ")"; }); 


bar.append("rect") 
.attr("x", function (d) { return x(d.x); }) 
.attr("y", function (d) { return y(d.y0 + d.y); }) 
.attr("height", function (d) { return y(d.y0) - y(d.y0 + d.y); }) 
.attr("width", x.rangeBand()) 


bar.append("text") 
    .attr("x", function (d) { return x(d.x); }) 
    .attr("y", function (d) { return y(d.y0 + d.y); }) 
    .attr("dy", ".35em") 
    .attr('style', 'font-size:13px') 
    .text(function (d) { if (d.y != 0) { sum += d.y; return "$" + d.y; } }) 
    .style('fill', 'black'); 

bar.append("text") 
    .attr("x", function (d) { return x(d.x); }) 
.attr("y", function (d) { return y(d.y0 + d.y); }) 
    .attr("dy", ".35em") 
    .attr('style', 'font-size:13px') 
    .text(sum) 
    .style('fill', 'black'); 

的jsfiddle:http://fiddle.jshell.net/1fsm8cst/3/

+0

也许你可以包括带有示例数据的工作示例。在您的文章中直接插入工作代码片段非常简单。 –

+0

http://fiddle.jshell.net/1fsm8cst/2/。请在这个小提琴中找到我的代码。 –

+0

标签值在您的小提琴中是正确的...每个标签都是单个栏的值,而不是您声称的总数。 –

回答

1

垂直总结不自然与栈布局,因为它团体层,但D3有很多的功能,以帮助。在这种情况下,d3.nest,d3.sum和d3.values(关于d3.sum的真正好处是它忽略了NaN值)。通过这些,您可以按月对数据进行汇总,然后可以使用相同的坐标系和比例来定位汇总的元素。

var margin = {top: 20, right: 300, bottom: 35, left: 50}; 
 

 
    var width = 760 - margin.left - margin.right, 
 
    height = 400 - margin.top - margin.bottom; 
 

 

 

 
    var svg = d3.select("body") 
 
    .append("svg") 
 
    .attr("width", width + margin.left + margin.right) 
 
    .attr("height", height + margin.top + margin.bottom) 
 
    .append("g") 
 
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 
 

 

 

 
    /* Data in strings like it would be if imported from a csv */ 
 

 
    var data = [ 
 
    { month: "Jan", MobileCoupon: "430000", Bonus: "240000", Promotions: "200000", Merchandise: "150000" }, 
 
    { month: "Feb", MobileCoupon: "250000", Bonus: "440000", Promotions: "200000", Merchandise: "150000" }, 
 
    { month: "Mar", MobileCoupon: "350000", Bonus: "180000", Promotions: "200000", Merchandise: "150000" }, 
 
    ]; 
 

 
    var parse = d3.time.format("%b").parse; 
 

 

 
    // Transpose the data into layers 
 
    var dataset = d3.layout.stack()(["MobileCoupon", "Bonus", "Promotions", "Merchandise"].map(function(fruit) { 
 
    return data.map(function(d) { 
 
     return {x: parse(d.month), y: +d[fruit]}; 
 
    }); 
 
    })); 
 

 
    var months = d3.nest() 
 
    .key(function(d){return parse(d.month)}) 
 
    .rollup(function(leaves){ 
 
     return d3.sum(leaves, function(d) {return d3.sum(d3.values(d))}); 
 
    }) 
 
    .entries(data); 
 

 
    // Set x, y and colors 
 
    var x = d3.scale.ordinal() 
 
    .domain(dataset[0].map(function(d) { return d.x; })) 
 
    .rangeRoundBands([10, width-10], 0.35); 
 

 
    var y = d3.scale.linear() 
 
    .domain([0, d3.max(dataset, function(d) { return d3.max(d, function(d) { return d.y0 + d.y; }); })]) 
 
    .range([height, 0]); 
 

 
    var colors = ["#3D0000", "#d25c4d", "#f2b447", "#d9d574"]; 
 

 
    // Define and draw axes 
 
    var yAxis = d3.svg.axis() 
 
    .scale(y) 
 
    .orient("left") 
 

 
    .ticks(5) 
 
    .tickSize(-width, 0, 0) 
 
    .tickFormat(d3.format("$,s")); 
 

 
    var xAxis = d3.svg.axis() 
 
    .scale(x) 
 
    .orient("bottom") 
 
    .tickFormat(d3.time.format("%b")); 
 

 
    svg.append("g") 
 
    .attr("class", "y axis") 
 
    .attr("transform", "translate(0,0)") 
 
    .call(yAxis); 
 

 

 
    svg.append("g") 
 
    .call(xAxis) 
 
    .attr("class", "x axis") 
 
    .attr("transform", "translate(0," + height + ")") 
 
    .call(xAxis); 
 

 
    // Create groups for each series, rects for each segment 
 
    var groups = svg.selectAll("g.cost") 
 
    .data(dataset) 
 
    .enter().append("g") 
 
    .attr("class", "cost") 
 
    .style("fill", function(d, i) { return colors[i]; }); 
 

 
// var svg = d3.select("svg"); 
 
    var bar = groups.selectAll("g") 
 
    .data(function(d) { return d; }) 
 
    .enter().append("g") 
 
    .attr("transform", function(d, i) { 
 
     return "translate(" + x(d.x) + ", 0)"; 
 
    }); 
 

 
    var sum=0; 
 
    bar.append("rect") 
 
    .attr("y", function(d) { return y(d.y0 + d.y); }) 
 
    .attr("height", function(d) { return y(d.y0) - y(d.y0 + d.y); }) 
 
    .attr("width", x.rangeBand()) 
 

 
    bar.append("text") 
 
    .attr("x", -6) 
 
    .attr("y", function(d) { return y(d.y0 + d.y); }) 
 
    .attr("dy", ".35em") 
 
    .text(function(d) {sum+=d.y; return d3.format("$,s")(d.y); }); 
 

 
    columns = svg.append("g") 
 
    .selectAll("text").data(months) 
 
    .enter().append("text") 
 
    .attr("x", function(d){ 
 
     return x(d.key) + x.rangeBand()/2 
 
    }) 
 
    .attr("y", function (d) { 
 
     return y(d.values); 
 
    }) 
 
    .attr("dy", "1.35em") 
 
    .attr('style', 'font-size:13px') 
 
    .text(function (d){ 
 
     return d3.format("$,s")(d.values); 
 
    }) 
 
    .style({fill: 'black', "text-anchor": "middle"}); 
 

 
    // svg.call(tip); 
 

 
    // Draw legend 
 
    var legend = svg.selectAll(".legend") 
 
    .data(colors) 
 
    .enter().append("g") 
 
    .attr("class", "legend") 
 
    .attr("transform", function(d, m) { return "translate(90," + (m+5) * 20 + ")"; }); 
 

 
    legend.append("rect") 
 
    .attr("x", width - 18) 
 
    .attr("width", 18) 
 
    .attr("height", 18) 
 
    .style("fill", function(d, i) {return colors.slice().reverse()[i];}); 
 

 
    legend.append("text") 
 
    .attr("x", width + 5) 
 
    .attr("y", 9) 
 
    .attr("dy", ".35em") 
 
    .style("text-anchor", "start") 
 
    .text(function(d, i) { 
 
     switch (i) { 
 
     case 0: return "Mobile Coupon"; 
 
     case 1: return "Bonus"; 
 
     case 2: return "Promotions"; 
 
     case 3: return "Merchandise"; 
 
     } 
 
    });
svg { 
 
     font: 10px sans-serif; 
 
     shape-rendering: crispEdges; 
 
    } 
 

 
    .axis path, 
 
    .axis line { 
 
     fill: none; 
 
     stroke: black; 
 
     shape-rendering: crispEdges; 
 
    } 
 

 
    path.domain { 
 
     stroke: none; 
 
    } 
 

 
    .y .tick line { 
 
     stroke: #ddd;} 
 

 

 
    text { 
 
     font: 10px sans-serif; 
 
     text-anchor: end; 
 
    } 
 

 

 

 
    .d3-tip { 
 
     line-height: 1; 
 
     font-weight: bold; 
 
     padding: 12px; 
 
     background: rgba(0, 0, 0, 0.8); 
 
     color: #fff; 
 
     border-radius: 2px; 
 
    } 
 

 
    /* Creates a small triangle extender for the tooltip */ 
 
    .d3-tip:after { 
 
     box-sizing: border-box; 
 
     display: inline; 
 
     font-size: 10px; 
 
     width: 100%; 
 
     line-height: 1; 
 
     color: rgba(0, 0, 0, 0.8); 
 
     content: "\25BC"; 
 
     position: absolute; 
 
     text-align: center; 
 
    } 
 

 
    /* Style northward tooltips differently */ 
 
    .d3-tip.n:after { 
 
     margin: -1px 0 0 0; 
 
     top: 100%; 
 
     left: 0; 
 
    } 
 
    .legend 
 
    { 
 
     position: relative; 
 
     top: -401px; 
 
     left: 380px; 
 
    }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

0

我目前在Javascript和D3是初学者。 希望我的解决方案服务于目的: http://jsfiddle.net/sandeepedara/n3ew5sqq/

var margin = {top: 20, right: 300, bottom: 35, left: 50}; 

var width = 760 - margin.left - margin.right, 
    height = 400 - margin.top - margin.bottom; 



var svg = d3.select("body") 
    .append("svg") 
    .attr("width", width + margin.left + margin.right) 
    .attr("height", height + margin.top + margin.bottom) 
    .append("g") 
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 



/* Data in strings like it would be if imported from a csv */ 

var data = [ 
    { month: "Jan", MobileCoupon: "430000", Bonus: "240000", Promotions: "200000", Merchandise: "150000" }, 
    { month: "Feb", MobileCoupon: "250000", Bonus: "440000", Promotions: "200000", Merchandise: "150000" }, 
    { month: "Mar", MobileCoupon: "350000", Bonus: "180000", Promotions: "200000", Merchandise: "150000" }, 
]; 

for (var key in data) { 
var sum=0; 
    if (data.hasOwnProperty(key)) { 
     var obj = data[key]; 

     for (var prop in obj) { 

      // important check that this is objects own property 
      // not from prototype prop inherited 
      if(obj.hasOwnProperty(prop)){ 
       if(prop=="month"){console.log("month");} 
       else{   
       sum = sum + parseInt(obj[prop]); 
       obj.sum = sum; 
      } 
      } 
     } 
    } 
} 

var parse = d3.time.format("%b").parse; 


// Transpose the data into layers 
var dataset = d3.layout.stack()(["MobileCoupon", "Bonus", "Promotions", "Merchandise","sum"].map(function(fruit) { 
    return data.map(function(d) { 
    return {x: parse(d.month), y: +d[fruit]}; 
    }); 
})); 


// Set x, y and colors 
var x = d3.scale.ordinal() 
    .domain(dataset[0].map(function(d) { return d.x; })) 
    .rangeRoundBands([10, width-10], 0.35); 

var y = d3.scale.linear() 
    .domain([0, d3.max(dataset, function(d) { return d3.max(d, function(d) { return d.y0 + d.y; }); })]) 
    .range([height, 0]); 

var colors = ["#3D0000", "#d25c4d", "#f2b447", "#d9d574"]; 

// Define and draw axes 
var yAxis = d3.svg.axis() 
    .scale(y) 
    .orient("left") 

    .ticks(5) 
.tickSize(-width, 0, 0) 
    .tickFormat(function(d) { return "$" + d }); 

var xAxis = d3.svg.axis() 
    .scale(x) 
    .orient("bottom") 
    .tickFormat(d3.time.format("%b")); 

svg.append("g") 
    .attr("class", "y axis") 
    .attr("transform", "translate(0,0)") 
    .call(yAxis); 


svg.append("g") 
.call(xAxis) 
    .attr("class", "x axis") 
    .attr("transform", "translate(0," + height + ")"); 
    //.call(xAxis); 


// Create groups for each series, rects for each segment 
var groups = svg.selectAll("g.cost") 
    .data(dataset) 
    .enter().append("g") 
    .attr("class", "cost") 
    .style("fill", function(d, i) { return colors[i]; }); 




    var svg = d3.select("svg"); 
    var bar = groups.selectAll("g") 
    .data(function(d) { return d; }) 
    .enter().append("g") 
    .attr("transform", function(d, i) { return "translate(0," + i * y(d.y0) - y(d.y0 + d.y) + ")"; }); 


bar.append("rect") 
    .attr("x", function(d) { return x(d.x); }) 
    .attr("y", function(d) { return y(d.y0 + d.y); }) 
    .attr("height", function(d) { return y(d.y0) - y(d.y0 + d.y); }) 
    .attr("width", x.rangeBand()) 


bar.append("text") 
    .attr("x", function(d) { return x(d.x); }) 
    .attr("y", function(d) { return y(d.y0 + d.y); }) 
    .attr("dy", ".35em") 
    .text(function(d) { return d.y; }); 

    svg.call(tip); 





// Draw legend 
var legend = svg.selectAll(".legend") 
    .data(colors) 
    .enter().append("g") 
    .attr("class", "legend") 
    .attr("transform", function(d, m) { return "translate(90," + (m+5) * 20 + ")"; }); 

legend.append("rect") 
    .attr("x", width - 18) 
    .attr("width", 18) 
    .attr("height", 18) 
    .style("fill", function(d, i) {return colors.slice().reverse()[i];}); 

legend.append("text") 
    .attr("x", width + 5) 
    .attr("y", 9) 
    .attr("dy", ".35em") 
    .style("text-anchor", "start") 
    .text(function(d, i) { 
    switch (i) { 
     case 0: return "Mobile Coupon"; 
     case 1: return "Bonus"; 
     case 2: return "Promotions"; 
     case 3: return "Merchandise"; 
    } 
    }); 
+0

你问题不对。所需的输出如图所示。 http://pasteboard.co/1AeNB6X4.jpg –

+0

@AkshayShinde,我建议单词“Sum”并不是真的有必要吗? –