Last active
December 16, 2015 19:09
-
-
Save And-How/5482876 to your computer and use it in GitHub Desktop.
bar stacked to grouped with negative numbers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<script src="http://mbostock.github.com/d3/d3.v2.js"></script> | |
<!--modified from https://groups.google.com/forum/#!msg/d3-js/gzSkw5skLXo/SKjMLwEeIsUJ--> | |
<title>barStack</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 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 | |
} | |
function barGroup(d) { | |
var l = d[0].length | |
while (l--) { | |
d.forEach(function(d) { | |
d=d[l] | |
d.size = Math.abs(d.y); | |
d.y0 = Math.max(0, d.y); | |
}) | |
} | |
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; | |
} | |
/* Here is an example */ | |
var data = [[{x:1,y:3},{x:2,y:6},{x:3,y:-3}], | |
[{x:1,y:4},{x:2,y:-2},{x:3,y:-9}], | |
[{x:1,y:10},{x:2,y:-3},{x:3,y:4}]] | |
var h=500 | |
,w=500 | |
,margin=10 | |
,color = d3.scale.category10() | |
,x = d3.scale.ordinal() | |
.domain(d3.range(data.length)) | |
.rangeRoundBands([0,w], .1) | |
//for grouped | |
xGroup = d3.scale.ordinal() | |
.domain(d3.range(data.length)) | |
.rangeBands([0, x.rangeBand()]); | |
y = d3.scale.linear() | |
.domain([returnDomain().min, returnDomain().max]) | |
.range([h, 0]) | |
.nice() | |
,xAxis = d3.svg.axis().scale(x).orient("bottom").tickSize(6, 0) | |
,yAxis = d3.svg.axis().scale(y).orient("left") | |
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") | |
svg.append("g").attr("class","axis x") | |
svg.append("g").attr("class","axis y") | |
var layout = 0,dur=0 | |
redraw() | |
dur = 1500 | |
function redraw() { | |
if (layout=!layout) { | |
barStack(data) | |
y.domain(data.extent) | |
/* Readjust the range to width and height */ | |
x.rangeRoundBands([margin,w-margin], .1) | |
y.range([h-margin,0+margin]) | |
/* Reposition and redraw axis */ | |
svg.select(".x.axis") | |
.transition().duration(dur) | |
.attr("transform","translate (0 "+y(0)+")") | |
.call(xAxis.orient("bottom")) | |
svg.select(".y.axis") | |
.transition().duration(dur) | |
.attr("transform","translate ("+x(0)+" 0)") | |
.call(yAxis.orient("left")) | |
/* Reposition the elements */ | |
/* | |
svg.selectAll(".series rect") | |
.transition().duration(dur) | |
.attr("x",function(d,i) { return x(d.x)}) | |
.attr("y",function(d) { return y(d.y0)}) | |
.attr("height",function(d) { return y(0)-y(d.size)}) | |
.attr("width",x.rangeBand()) | |
*/ | |
svg.selectAll(".series") | |
.attr("transform", function (d, i) { return "translate(0)" ; }); | |
svg.selectAll("rect") | |
.transition().duration(dur) | |
.attr("x",function(d,i) { return x(i); }) | |
.attr("y",function(d,i) { return y(d.y0) ;}) | |
.attr("width", function(d,i) { return x.rangeBand(); }) | |
.attr("height",function(d,i) { return (y(0)-y(d.size)); }) | |
} else { | |
barGroup(data), | |
svg.selectAll(".series") | |
.attr("transform", function (d, i) { return "translate(" + xGroup(i) + ")" ; }) | |
//rects | |
svg.selectAll("rect") | |
.transition().duration(dur) | |
//.attr("x", function(d, i, j) { | |
// return x(d.x) + x.rangeBand() / xGroup.length * j; }) | |
.attr("x",function(d,i) { return x(i) ; }) | |
.attr("y",function(d,i) { return y(d.y0);}) | |
.attr("width", function(d,i) { return xGroup.rangeBand(); }) | |
.attr("height",function(d,i) { return (y(0)-y(d.size)); }) | |
} | |
d3.select("body").append("button") | |
.attr("type","button") | |
.text("Change Layout") | |
.style("position","absolute") | |
.style("left","5px") | |
.style("top","5px") | |
.on("click",redraw) | |
} | |
function returnDomain () { | |
var domain = {}; | |
domain.min = Math.min(d3.min(d3.extent(data)),0); | |
domain.max = Math.max(d3.max(d3.extent(data)),0); | |
return domain; | |
} | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment