サンプル
例1
* ただし、負の値は未対応<!DOCTYPE html> <meta charset="utf-8"> <style> body { font: 10px sans-serif; } .axis path, .axis line { fill: none; stroke: #000; shape-rendering: crispEdges; } .bar { fill: steelblue; } </style> <body> <script src="">https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"> <script> var dataset = [ {graphId: "001", y1Val: 2, y2Val: 15, y3Val: 9, y4Val: 15}, {graphId: "002", y1Val: 3, y2Val: 17, y3Val: 4, y4Val: 12}, {graphId: "003", y1Val: 7, y2Val: 4, y3Val: 9, y4Val: 14}, ]; var isSorted = true; var margin = {top: 20, right: 20, bottom: 30, left: 40}, width = 960 - margin.left - margin.right, height = 500 - margin.top - margin.bottom; var xScale = d3.scale.ordinal() .rangeRoundBands([0, width], .1); var yScale = d3.scale.linear() .rangeRound([height, 0]); var colors = d3.scale.ordinal() .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b"]); var xAxis = d3.svg.axis() .scale(xScale) .orient("bottom"); var yAxis = d3.svg.axis() .scale(yScale) .orient("left") .tickFormat(d3.format(".2s")); 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 + ")"); colors.domain(d3.keys(dataset[0]).filter(function(key) { return key !== "graphId"; })); dataset.forEach(function(d) { var y0 = 0; d.xValues = colors.domain().map(function(name) { return {name: name, y0: y0, y1: y0 += +d[name]}; }); d.total = d.xValues[d.xValues.length - 1].y1; }); if (isSorted) { dataset.sort(function(a, b) { return b.total - a.total; }); } xScale.domain(dataset.map(function(d) { return d.graphId; })); yScale.domain([0, d3.max(dataset, function(d) { return d.total; })]); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis); svg.append("g") .attr("class", "y axis") .call(yAxis) .append("text") .attr("transform", "rotate(-90)") .attr("y", 6) .attr("dy", ".71em") .style("text-anchor", "end") .text("Population"); var state = svg.selectAll(".state") .data(dataset) .enter() .append("g") .attr("class", "g") .attr("transform", function(d) { return "translate(" + xScale(d.graphId) + ",0)"; }); state.selectAll("rect") .data(function(d) { return d.xValues; }) .enter() .append("rect") .attr("width", xScale.rangeBand()) .attr("y", function(d) { return yScale(d.y1); }) .attr("height", function(d) { return yScale(d.y0) - yScale(d.y1); }) .style("fill", function(d) { return colors(d.name); }); var legend = svg.selectAll(".legend") .data(colors.domain().slice().reverse()) .enter().append("g") .attr("class", "legend") .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; }); legend.append("rect") .attr("x", width - 18) .attr("width", 18) .attr("height", 18) .style("fill", colors); legend.append("text") .attr("x", width - 24) .attr("y", 9) .attr("dy", ".35em") .style("text-anchor", "end") .text(function(d) { return d; }); </script>
例2 : 負の値を対応版
<!DOCTYPE html> <html> <head> <script src="">http://mbostock.github.com/d3/d3.v2.js"> <title>Sample Stacked Bar Chart</title> <style> .axis text { font: 10px sans-serif; } .axis path, .axis line { fill: none; stroke: #000; shape-rendering: crispEdges; } </style> </head> <body> <script type="text/javascript" > function buildStackedBarChart(chartDataset) { var index = chartDataset[0].length; while (index--) { var positive = 0; var negative = 0; chartDataset.forEach(function(datum) { datum = datum[index]; datum.size = Math.abs(datum.y); if (datum.y <0) { datum.y0 = negative; negative -= datum.size; } else { datum.y0 = positive = positive + datum.size; } }) } chartDataset.extent= d3.extent(d3.merge(d3.merge(chartDataset.map(function(datum) { return datum.map(function(d) { return [d.y0, d.y0 - d.size]})})))); return chartDataset; } var dataset = [ [{y:3},{y:6},{y:-3}], [{y:4},{y:-2},{y:-9}], [{y:10},{y:-3},{y:4}] ]; var height = 500; var width = 500; var margin = 10; var colors = d3.scale.category10(); var xScale = d3.scale.ordinal() .domain(['abc','abc2','abc3']) .rangeRoundBands([margin, width - margin], .1) var yScale = d3.scale.linear() .range([height - margin, 0 + margin]); var xAxis = d3.svg.axis().scale(xScale).orient("bottom").tickSize(6, 0); var yAxis = d3.svg.axis().scale(yScale).orient("left"); buildStackedBarChart(dataset); yScale.domain(dataset.extent); svg = d3.select("body") .append("svg") .attr("height", height) .attr("width", width) svg.selectAll(".series") .data(dataset) .enter() .append("g") .classed("series", true) .style("fill", function(d, i) { return colors(i); }) .selectAll("rect") .data(Object) .enter() .append("rect") .attr("x", function(d, i) { return xScale(xScale.domain()[i]); }) .attr("y", function(d) { return yScale(d.y0)}) .attr("height", function(d) { return yScale(0) - yScale(d.size)}) .attr("width", xScale.rangeBand()) svg.append("g") .attr("class", "axis x") .attr("transform", "translate (0, " + yScale(0) + ")") .call(xAxis) svg.append("g") .attr("class", "axis y") .attr("transform", "translate (" + (xScale(margin) - 10) + ", 0)") .call(yAxis) </script> </body> </html>
補足
* 上記の例2にツールチップをつけたサンプルは、以下の関連記事を参照のこと。http://blogs.yahoo.co.jp/dk521123/35480801.html
参考文献
http://bl.ocks.org/mbostock/3886208* 負の値対応版
http://bl.ocks.org/ZJONSSON/2975320
http://bl.ocks.org/ZJONSSON/2979974
http://bl.ocks.org/milroc/2991587