Last active
November 5, 2015 14:36
-
-
Save uafrazier/833042ec4d3381a15c67 to your computer and use it in GitHub Desktop.
D3: Stacked Bar Chart (Smartphone OS Marketshare)
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 lang="en"> | |
<head> | |
<meta charset="UTF-8" /> | |
<title>Knight Center D3: Stack Bar Chart</title> | |
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> | |
<style type="text/css"> | |
@import url(http://fonts.googleapis.com/css?family=Oswald:700,400); | |
@import url(http://fonts.googleapis.com/css?family=Open+Sans); | |
body { | |
font-family: oswald, arial, sans-serif; | |
color: #333; | |
} | |
p { | |
font-family: open sans, arial, sans-serif; | |
} | |
a:link { | |
color: #3A96B7; | |
text-decoration: none; | |
} | |
a:hover { | |
text-decoration: underline; | |
} | |
a:visited { | |
color: #3A96B7; | |
} | |
a:active { | |
color: steelBlue; | |
} | |
.container { | |
width: 900px; | |
margin-left: auto; | |
margin-right: auto; | |
margin-top: 50px; | |
margin-bottom: 50px; | |
padding: 20px 50px; | |
background: #fff; | |
box-shadow: 0 0 5px #999999; | |
} | |
.source { | |
font-family: oswald, arial, sans-serif; | |
font-weight: bold; | |
font-size: .75em; | |
} | |
svg { | |
font-size: 10px; | |
shape-rendering: crispEdges; | |
} | |
.axis path, | |
.axis line { | |
fill: none; | |
stroke: #000; | |
} | |
path.domain { | |
stroke: none; | |
} | |
.y .tick line { | |
stroke: #ddd; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="container"> | |
<h1>Worldwide Smartphone OS Market Share, 2012-2015 Q2</h1> | |
<p>Quarter 2 smartphone data for 2015 has now been released. Measuring <a href="http://www.investopedia.com/terms/y/year-over-year.asp">year-over-year</a> performance, the trend of Android phone dominance of the marketplace continues.</p> | |
<p><span class="source">Source: <a href="https://www.idc.com/prodserv/smartphone-os-market-share.jsp">ICT, August 2015</a></span></p> | |
</div> | |
<script type="text/javascript"> | |
// Setup margins using Bostock's method | |
var margin = {top: 25, right: 160, bottom: 25, left: 30}; | |
var width = 900 - margin.left - margin.right, | |
height = 500 - margin.top - margin.bottom; | |
// Setup svg | |
var svg = d3.select(".container") | |
.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 + ")"); | |
var data = [ | |
{ year: "2012", android: "69.3", ios: "16.6", windows_phone: "3.1", blackberry_os: "4.9", other: "6.1" }, | |
{ year: "2013", android: "79.8", ios: "12.9", windows_phone: "3.4", blackberry_os: "2.8", other: "1.2" }, | |
{ year: "2014", android: "84.8", ios: "11.6", windows_phone: "2.5", blackberry_os: "0.5", other: "0.7" }, | |
{ year: "2015", android: "82.8", ios: "13.9", windows_phone: "2.6", blackberry_os: "0.3", other: "0.4" }, | |
]; | |
var parse = d3.time.format("%Y").parse; | |
// Transpose the data into layers by operating system | |
var dataset = d3.layout.stack()(["android", "ios", "windows_phone", "blackberry_os", "other"].map(function(os) { | |
return data.map(function(d) { | |
return {x: parse(d.year), y: +d[os]}; | |
}); | |
})); | |
// Set x & y scales and colors | |
var x = d3.scale.ordinal() | |
.domain(dataset[0].map(function(d) { return d.x; })) | |
.rangeRoundBands([10, width-10], 0.02); | |
var y = d3.scale.linear() | |
.domain([0, 100]) | |
.range([height, 0]); | |
var colors = ['#7fc97f','#beaed4','#fdc086','#ffff99','#386cb0']; | |
// Define and draw axes | |
var yAxis = d3.svg.axis() | |
.scale(y) | |
.orient("left") | |
.ticks(5) | |
.tickSize(-width, 0, 0) | |
.tickFormat( function(d) { return d + '%' } ); | |
var xAxis = d3.svg.axis() | |
.scale(x) | |
.orient("bottom") | |
.tickFormat(d3.time.format("%Y")); | |
svg.append("g") | |
.attr("class", "y axis") | |
.call(yAxis); | |
svg.append("g") | |
.attr("class", "x axis") | |
.attr("transform", "translate(0," + height + ")") | |
.call(xAxis); | |
// Create groups for each series, rects for each segment | |
var groups = svg.selectAll("g.percent") | |
.data(dataset) | |
.enter().append("g") | |
.attr("class", "percent") | |
.style("fill", function(d, i) { return colors[i]; }); | |
var rect = groups.selectAll("rect") | |
.data(function(d) { return d; }) | |
.enter() | |
.append("rect") | |
.attr("x", function(d) { return x(d.x); }) | |
.attr("y", function(d) { return y(d.y0 + d.y); }) | |
.attr("height", function(d) { return y(d.y0) - y(d.y0 + d.y); }) | |
.attr("width", x.rangeBand()) | |
.on("mouseover", function() { tooltip.style("display", null); }) | |
.on("mouseout", function() { tooltip.style("display", "none"); }) | |
.on("mousemove", function(d) { | |
var xPosition = d3.mouse(this)[0] - 15; | |
var yPosition = d3.mouse(this)[1] - 25; | |
tooltip.attr("transform", "translate(" + xPosition + "," + yPosition + ")"); | |
tooltip.select("text").text(d.y+'%'); | |
}); | |
// Create legend | |
var legend = svg.selectAll(".legend") | |
.data(colors) | |
.enter().append("g") | |
.attr("class", "legend") | |
.attr("transform", function(d, i) { return "translate(30," + i * 19 + ")"; }); | |
legend.append("rect") | |
.attr("x", width - 18) | |
.attr("width", 18) | |
.attr("height", 18) | |
.style("fill", function(d, i) {return colors.slice().reverse()[i];}); | |
legend.append("text") | |
.attr("x", width + 5) | |
.attr("y", 9) | |
.attr("dy", ".35em") | |
.style("text-anchor", "start") | |
.text(function(d, i) { | |
switch (i) { | |
case 0: return "Other"; | |
case 1: return "Blackberry OS"; | |
case 2: return "Windows Phone"; | |
case 3: return "IOS"; | |
case 4: return "Android"; | |
} | |
}); | |
// Create tooltip, initial display is hidden | |
var tooltip = svg.append("g") | |
.attr("class", "tooltip") | |
.style("display", "none"); | |
tooltip.append("rect") | |
.attr("width", 40) | |
.attr("height", 20) | |
.attr("fill", "white") | |
.style("opacity", 0.5); | |
tooltip.append("text") | |
.attr("x", 20) | |
.attr("dy", "1.2em") | |
.style("text-anchor", "middle") | |
.attr("font-size", "12px") | |
.attr("font-weight", "bold"); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment