Stacked Bars
by ramnathv
HTML
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="//rawgit.com/gka/d3-jetpack/master/d3-jetpack.js"></script>
<script src="//rawgit.com/kristw/75b61f9beeab9b530612/raw/389e984e4041117a9185cf6edad9f6b85a38097a/d3kit.min.js"></script>
<script src="//rawgit.com/DarkMarmot/kodama/master/kodama.js"></script>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="//cdn.rawgit.com/ramnathv/a5a3199538f86817ec1b/raw/96dde67abbf386b571d62dc366f15dc057085092/visutils.js"></script>
<div class="container-fluid" id="main">
<div class="row">
<div class="col-xs-12 col-md-3">
<div id="chart"></div>
<div class="btn-group" role="group" aria-label="...">
<button class="btn btn-default active g1" data-option='stack'>
Stack
</button>
<button class="btn btn-default g2" data-option='stack'>
Dodge
</button>
<button class="btn btn-default g1" data-option='separate'>
Separate
</button>
</div>
</div>
</div>
</div>
CSS
.btn-group{
display: 'block';
}
CoffeeScript
alphabet = (i) -> String.fromCharCode(i + 65)
make_data = (N) ->
d3.range(N).map (i) ->
x: alphabet(i), y1: (i + 1), y2: (i + 1)*1.5, y3: (i + 1)*2
mydata = make_data(5)
d1 = ['y1', 'y2', 'y3'].map (k) ->
mydata.map (d) ->
{x: d.x, y: d[k]}
stackedBarConstructor = (skeleton) ->
layers = skeleton.getLayerOrganizer()
S =
x: d3.scale.ordinal()
y: d3.scale.linear()
c: d3.scale.category20()
A =
x: (d) -> d.x
y: (d) -> d.y
y0: (d) -> d.y0
layers.create(['bars'])
visualize = ->
data = skeleton.data()
opts = skeleton.options()
H = skeleton.getInnerHeight()
W = skeleton.getInnerWidth()
S.x.rangeRoundBands([0, W], 0.05)
.domain(d3.range(5).map(alphabet))
S.y.range([H, 0])
.domain([0, 40])
rows = layers.get('bars').selectAll('.row')
.data(data)
rows.enter().append('g.row')
.style
fill: (d, i) -> S.c(i)
stroke: 'whitesmoke'
yAccessor =
stack: (i) -> (d) -> S.y(A.y(d) + A.y0(d))
separate: (i) -> (d) -> S.y(A.y(d)) - 100*i
rects = rows.selectAll('rect.bar')
.data(Object)
rects.enter().append('rect.bar')
rects
.attr
x: (d) -> S.x A.x(d)
width: S.x.rangeBand()
y: (d) -> S.y(A.y(d) + A.y0(d))
height: (d) -> -S.y(A.y(d) + A.y0(d)) + S.y(A.y0(d))
d3.selectAll('.g1').on 'click', ->
d3.selectAll('.btn').classed('active', false)
opt = d3.select(@)
.classed('active', true)
.attr('data-option')
#rows = d3.selectAll('g.row')
###
rows.selectAll('rect.bar')
.transition()
.attr
y: (d, i) -> yAccessor[opt](i)
.transition()
.attr
x: (d) -> S.x A.x(d)
width: S.x.rangeBand()
###
rows.each (d, i) ->
d3.select(@).selectAll('rect.bar')
.transition()
#.delay((d, i) -> i/5*750)
.attr
...