-
-
Save emepyc/4319822 to your computer and use it in GitHub Desktop.
Horizontal stacked bar with update
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
{"description":"Horizontal stacked bar with update","endpoint":"","display":"svg","public":true,"require":[],"fileconfigs":{"gistfile1.txt":{"default":true,"vim":false,"emacs":false,"fontSize":12},"inlet.js":{"default":true,"vim":false,"emacs":false,"fontSize":12},"config.json":{"default":true,"vim":false,"emacs":false,"fontSize":12},"_.md":{"default":true,"vim":false,"emacs":false,"fontSize":12}},"tab":"edit","display_percent":0.414969725755848,"play":false,"loop":false,"restart":false,"autoinit":true,"pause":true,"loop_type":"period","bv":false,"nclones":15,"clone_opacity":0.4,"duration":3000,"ease":"linear","dt":0.01,"hidepanel":false} |
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
// This snippet implements a reusable stacked bar chart with transitions. | |
// Its purpose is to experiment with reusable charts (and transitions) | |
// as explained in: | |
// http://bost.ocks.org/mike/chart/ | |
var g = d3.select("svg") | |
.append("g") | |
var data1 = {jobs_counts : { counts : [2,6,7,2,1], | |
colors : ["green", "yellow", "red", "blue", "cyan"] | |
}, | |
total_job_count : 18, | |
logic_name : "analysis1" | |
}; | |
var data2 = {jobs_counts : { counts : [1,1,1,10,2], | |
colors : ["green", "yellow", "red", "blue", "cyan"] | |
}, | |
total_job_count : 15, | |
logic_name : "analysis1" | |
}; | |
var max_counts = 20; | |
// pChart is the reusable stacked bar chart implementation. | |
// In this example only a few methods are defined (API): | |
// -data: to update the data used by the pie chart (here this is internally used by the update method) | |
// -update: to update the pie chart with new data + transition | |
// -transition: returns a transition closure that is used to pudate the pie-chart (via its update method) | |
// -height: to update the height of the horizontal stacked bar. | |
// -barsmargin: to update the left space, used for the analysis label | |
var pChart = hStackedBarChart().data(data1).height(50).barsmargin(100); | |
pChart(g); | |
var t = pChart.transition(); | |
pChart.update(data1, t); | |
setTimeout(function(){console.log("ch1"); pChart.update(data2, t)}, 2000); | |
setTimeout(function(){console.log("ch2"); pChart.update(data1, t)}, 4000); | |
setTimeout(function(){console.log("ch3"); pChart.update(data2, t)}, 6000); | |
// The reusable horizontal stacked bar | |
function hStackedBarChart() { | |
var barsmargin = 80; | |
var stack = d3.layout.stack(); | |
var margin = {top: 10, right: 10, bottom: 10, left: 10}, | |
width = 460 - margin.left - margin.right, | |
height = 50; | |
var fontsize = 16; | |
var raw_data = {total_job_count : 4, | |
jobs_counts : { counts : [0,0,0,0,0], | |
colors : ["green", "yellow", "blue", "red", "cyan"] | |
}, | |
logic_name : "analysis1" | |
}; | |
var bChart = function(g){ | |
var data = bChart.transformData(raw_data); | |
var layers = stack(data); | |
// Only 1 layer | |
var gLayer = g.selectAll(".layer") | |
.data(layers) | |
.enter().append("svg:g") | |
.attr("class", "layer") | |
.style("fill", function(d, i) { return raw_data.jobs_counts.colors[i] }) | |
console.log(gLayer); | |
var gRects = gLayer.selectAll("g") | |
.data(function(d) {return d}) | |
.enter().append("g") | |
.attr("class", function(d,i){return "analysis" + (i+1)}) | |
.classed("bar", true); | |
gRects.append("svg:rect") | |
.attr("x", barsmargin) | |
// .attr("y", function(d) {console.log(d); return x(d.x)}) | |
.attr("y", 0) // at the top | |
.attr("height", height) | |
.attr("width", 0) | |
.each(function(d,i){this._type = "stacked"}); | |
// analysis label | |
g | |
.append("svg:g") | |
.attr("class", "analysis_label") | |
.attr("to_id", raw_data.logic_name) | |
.on("click", bChart.switch_type) | |
.append("svg:text") | |
.attr("x", 0) | |
.attr("y", bChart.height()/2 + bChart.fontsize()/2.5) | |
.attr("fill", "black") | |
.attr("font-size", fontsize) | |
.text(raw_data.logic_name); | |
// general counts label | |
g | |
.append("svg:text") | |
.attr("class", "count_label") | |
.attr("x", barsmargin + 10) | |
.attr("y", bChart.height()/2 + bChart.fontsize()/2.5) | |
.attr("fill", "black") | |
.attr("font-size", fontsize) | |
.text("0"); | |
gRects.append("svg:text") | |
.attr("x", barsmargin) | |
.attr("y", 0) | |
.attr("font-size", 10) | |
.attr("fill", "red") | |
.text(0) | |
.each(function(d,i){this._type = "stacked"}); | |
bChart.transition = function () { | |
var duration = 1000; | |
var delay = 0; | |
var newT = function (newlayers) { | |
y = bChart.new_scale(g, newlayers); | |
var layer = g.selectAll(".layer") | |
.data(newlayers); | |
var rect = layer.selectAll("rect") | |
.data(function(d) {return d}); | |
var text = layer.selectAll("text") | |
.data(function(d) {return d}); | |
layer.selectAll(".bar").call(bChart.redrawBars, duration, delay); | |
g.selectAll(".count_label") | |
.data(newlayers) | |
.transition() | |
.delay(function(d,i){return i*100}) | |
.duration(1000) | |
.attr("x", function(d,i){var l=layers.slice(-1)[0][0]; return(y(l.y0+l.y) + barsmargin + 10)}) | |
.text(function(d,i){var l=layers.slice(-1)[0][0]; return (l.y0 + l.y)}); | |
}; | |
return newT; | |
}; | |
bChart.update = function(new_raw_data, trans) { | |
bChart.data(new_raw_data); | |
var new_data = bChart.transformData(new_raw_data); | |
var new_layers = stack(new_data); | |
trans(new_layers); | |
layers = new_layers; | |
return; | |
}; | |
// live_overview(g, layers); | |
return gRects; | |
}; | |
bChart.fontsize = function (value) { | |
if (!arguments.length) return fontsize; | |
fontsize = value; | |
return bChart; | |
}; | |
bChart.data = function (value) { | |
if (!arguments.length) return raw_data; | |
raw_data = value; | |
return bChart; | |
}; | |
bChart.height = function (value) { | |
if (!arguments.length) return height; | |
height = value; | |
return bChart; | |
}; | |
bChart.barsmargin = function (value) { | |
if (!arguments.length) return barsmargin; | |
barsmargin = value; | |
return bChart; | |
}; | |
bChart.switch_type = function () { | |
console.log(d3.select(this).attr("to_id")); | |
d3.selectAll("." + d3.select(this).attr("to_id")) // these are g with rects | |
.each(function(d,i) { | |
if($(this).children("rect")[0]._type=="grouped"){ | |
$(this).children("rect")[0]._type="stacked"; | |
$(this).children("text")[0]._type="stacked"; | |
} else { | |
$(this).children("rect")[0]._type="grouped"; | |
$(this).children("text")[0]._type="grouped"; | |
} | |
$(this).children("rect")[0]._column=i; | |
$(this).children("text")[0]._column=i; | |
}) | |
.call(bChart.redrawBars, 300, 10); | |
}; | |
bChart.redrawBars = function (bar, time, delay) { | |
var height = bChart.height(); | |
var n = bChart.data().jobs_counts.counts.length; | |
var indHeight = height/n; | |
var barsmargin = bChart.barsmargin(); | |
var rect = bar.selectAll("rect"); | |
rect | |
.transition() | |
.delay(function(d,i) {return i*delay}) | |
.duration(time) | |
.attr("x",function(d) {if (this._type == "stacked") {return barsmargin+y(d.y0)} else {return barsmargin}}) | |
.attr("y", function(d,i) {if (this._type == "stacked") {return 0} else {return this._column * indHeight}}) | |
.attr("width", function(d) {return y(d.y)}) | |
.attr("height", function() {if (this._type == "stacked") { return height } else {return indHeight}}); | |
var counts_labels = bar.selectAll("text"); | |
counts_labels | |
.transition() | |
.delay(function(d,i) {return i*delay}) | |
.duration(time) | |
.attr("x", function(d) {if (this._type == "stacked") {return barsmargin+y(d.y0+d.y)} else {return barsmargin+y(d.y)}}) | |
.attr("y", function(d,i) { if (this._type == "stacked") { return 0 } else { return this._column * indHeight + indHeight/2 + (16/2.5)}}) | |
.text(function(d){return (d.y)}) | |
}; | |
bChart.transformData = function (data) { | |
var transfData = []; | |
for (var i=0; i<data.jobs_counts.counts.length; i++) { | |
transfData[i] = []; | |
} | |
for (var j=0; j<data.jobs_counts.counts.length; j++) { | |
transfData[j].push({x:0, y:data.jobs_counts.counts[j]}) | |
} | |
return transfData; | |
}; | |
bChart.new_scale = function(svg, layers) { | |
var yStackMax = d3.max(layers, function(layer) { return d3.max(layer, function(d) { return d.y0 + d.y; }); }); | |
var width = 440; | |
var y = d3.scale.linear() | |
.domain([0, yStackMax]) | |
.range([0,width]); | |
return y; | |
} | |
return bChart; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment