Skip to content

Instantly share code, notes, and snippets.

@ChrisManess
Last active February 16, 2016 20:41
Show Gist options
  • Save ChrisManess/5f7f546eabce06cf5fa9 to your computer and use it in GitHub Desktop.
Save ChrisManess/5f7f546eabce06cf5fa9 to your computer and use it in GitHub Desktop.
Norm Stacked Bars Widget Inc. Example
license: gpl-3.0
{
"Jan 01 2016":{
"widgetA":197,
"widgetB":4,
"widgetC":37,
"widgetD":2,
"widgetE":50
},
"Feb 01 2016":{
"widgetA":181,
"widgetB":5,
"widgetC":38,
"widgetD":2,
"widgetE":48
},
"Mar 01 2016":{
"widgetA":171,
"widgetB":7,
"widgetC":39,
"widgetD":4,
"widgetE":46
},
"Apr 01 2016":{
"widgetA":168,
"widgetB":9,
"widgetC":40,
"widgetD":6,
"widgetE":45
},
"May 01 2016":{
"widgetA":178,
"widgetB":10,
"widgetC":39,
"widgetD":5,
"widgetE":44
},
"Jun 01 2016":{
"widgetA":189,
"widgetB":12,
"widgetC":38,
"widgetD":7,
"widgetE":43
},
"Jul 01 2016":{
"widgetA":201,
"widgetB":15,
"widgetC":36,
"widgetD":8,
"widgetE":42
},
"Aug 01 2016":{
"widgetA":202,
"widgetB":16,
"widgetC":35,
"widgetD":9,
"widgetE":43
},
"Sep 01 2016":{
"widgetA":180,
"widgetB":19,
"widgetC":36,
"widgetD":12,
"widgetE":42
},
"Oct 01 2016":{
"widgetA":176,
"widgetB":19,
"widgetC":37,
"widgetD":13,
"widgetE":41
},
"Nov 01 2016":{
"widgetA":166,
"widgetB":23,
"widgetC":38,
"widgetD":14,
"widgetE":40
},
"Dec 01 2016":{
"widgetA":185,
"widgetB":26,
"widgetC":38,
"widgetD":15,
"widgetE":39
}
}
<!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;
}
.x.axis path {
/*display: none;*/
}
</style>
<body>
<div id="widgets" class="chart">
<div class="title">
<h2>Widgets Inc. Revenue 2016</h2>
</div>
</div>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/regression/1.3.0/regression.min.js" charset="utf-8"></script>
<script src="normstackbar.js"></script>
<script>
$(document).ready(
function() {
viewPortWidth = 600;
viewPortHeight = 400;
chartHeight = (viewPortHeight) - 50;
var parsedData = [];
var regressionData = [];
var keys;
var margin = {
top: 10,
right: 20,
bottom: 20,
left: 40
};
var color = d3.scale.ordinal()
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
d3.json("data.json", function(error, data) {
if (error) throw error;
keys = Object.keys(data);
for (var i = 0; i < keys.length; i++) {
var d = data[keys[i]];
d.date = new Date(keys[i]);
parsedData.push(d);
}
var titleMapA = {"widgetA": "Widget A",
"widgetB": "Widget B",
"widgetC": "Widget C",
"widgetD": "Widget D",
"widgetE": "Widget E"
};
renderNormStackedBar("#widgets", viewPortWidth, chartHeight, margin, 125, 0, color, parsedData, keys, function(key) {
return key == "widgetA" ||
key == "widgetB" ||
key == "widgetC" ||
key == "widgetD" ||
key == "widgetE";
}, titleMapA, "vertical", 140, "% of Revenue");
});
}
);
</script>
function renderNormStackedBar(chartDiv, baseWidth, baseHeight, margin, adjustmentForLegend,
rangeBandAdjustment, color, parsedData, keys, fliterCallback, legendMap,
legendOrientation, legendOffset, scaleText) {
if(typeof legendOffset === "undefined"){
legendOffset = 20;
}
var width = baseWidth - margin.left - margin.right,
height = baseHeight - margin.top - margin.bottom;
var graphWidth = width-adjustmentForLegend;
var x = d3.scale.ordinal()
.rangeRoundBands([0, graphWidth], .1);
var y = d3.scale.linear()
.rangeRound([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(d3.format(".0%"));
var svg = d3.select(chartDiv).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 + ")");
color.domain(d3.keys(parsedData[0]).filter(fliterCallback));
parsedData.forEach(function(d) {
var y0 = 0;
d.added = color.domain().map(function(name) {
return {
name: name,
y0: y0,
y1: y0 += +d[name]
};
});
d.added.forEach(function(d) {
d.y0 /= y0;
d.y1 /= y0;
});
});
parsedData.sort(function(a, b) {
return a.date - b.date;
});
var x2 = d3.time.scale()
.domain([parsedData[0].date, parsedData[parsedData.length - 1].date])
.range([0, graphWidth]);
var x2Axis = d3.svg.axis()
.scale(x2)
.orient("bottom")
.tickFormat(d3.time.format('%b'));
x.domain(parsedData.map(function(d) {
return d.date;
}));
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(" + (20+((x.rangeBand()-rangeBandAdjustment)/2)) + "," + height + ")")
.call(x2Axis);
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(scaleText);
var definedGroup = svg.selectAll(".definedGroup")
.data(parsedData)
.enter().append("g")
.attr("class", "g")
.attr("transform", function(d) {
return "translate(" + (x2(d.date)+20) + ",0)";
});
definedGroup.selectAll("rect")
.data(function(d) {
return d.added;
})
.enter().append("rect")
.attr("width", x.rangeBand()-rangeBandAdjustment)
.attr("y", function(d) {
var f = 0
if (!isNaN(d.y1)) {
f = y(d.y1);
}
return f;
})
.attr("height", function(d) {
var f = 0
if (!isNaN(y(d.y0) - y(d.y1))) {
f = y(d.y0) - y(d.y1);
}
return f;
})
.style("fill", function(d) {
return color(d.name);
});
var legend = svg.selectAll(".legend")
.data(color.domain().slice().reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) {
var transString = "translate(";
if(legendOrientation == "horizontal"){
transString += "" + (i * legendOffset - width + adjustmentForLegend) + "," + (margin.top * -1 / 2 - 10);
} else if(typeof legendOrientation === "undefined" || legendOrientation == "vertical"){
transString += "0," + (i * 20);
} else {
throw "Error: Legend orientation must either be undefined or one of the following values: horizontal, vertical.";
}
transString += ")";
return transString;
});
legend.append("rect")
.attr("x", width - 12)
.attr("width", 18)
.attr("height", 18)
.style("fill", color)
.style("opacity", 0.75);
legend.append("text")
.attr("x", width - 18)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) {
return legendMap[d];
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment