<!DOCTYPE html>
<html>
<head>
<title>US Historical Energy Consumption</title>
<script type="text/javascript" src="//d3js.org/d3.v3.min.js"></script>
<script type="text/javascript" src="//code.jquery.com/jquery-1.8.3.min.js"></script>
<!--<script src="//code.jquery.com/jquery-1.8.3.min.js" type="text/javascript" charset="utf-8"></script>
<script src="jquery.tipsy.js" type="text/javascript" charset="utf-8"></script>
<link rel="stylesheet" href="//onehackoranother.com/projects/jquery/tipsy/stylesheets/tipsy.css" type="text/css" title="no title" charset="utf-8"/> -->
<style type="text/css">
body { font-size: 11px; font-family: Arial, "Helvetica Neue", Helvetica, sans-serif; }
.axis path, line { stroke: #000; fill:none; shape-rendering: crispEdges;}
line.tick { stroke: #cccccc; opacity:.4; }
.arc path {
stroke: #fff;
}
div#stack { width: 550px; float:left; }
div#pie { width: 350px; float:left; }
.yLabels { stroke: none; font-size: 1em; fill:#191919; }
.donutLabels { font-size:12px; font-weight: bold; stroke: none; fill:white; }
.underlay { visibility: hidden; pointer-events:all; }
.underlay rect { fill:gray; opacity:.3; }
.tooltip { position:absoulte; }
</style>
</head>
<body>
<div id="stack">
</div>
<div id="pie">
</div>
<script type="text/javascript">
// global variables
var margin = {t:20, r:20, b:20, l:30 },
w1 = 550 - margin.l - margin.r,
w2 = 300 - margin.r,
h = 350 - margin.t - margin.b,
x = d3.time.scale().range([0, w1]).clamp(true),
y = d3.scale.linear().range([h, 0]).domain([0, 110]),
color = d3.scale.ordinal().range(["#37A36A", "#3A5A64", "#DABD49", "#C78739", "#8AB8D9", "#A81F5E"]),
formatTime = d3.time.format("%Y").parse;
var dataChange,
latest,
data;
// settings for stacked area chart
var stacked = d3.select("#stack").append("svg")
.attr("width", w1 + margin.l + margin.r)
.attr("height", h + margin.t + margin.b)
.append("g")
.attr("class", "stackWrapper")
.attr("transform", "translate(" + margin.l + "," + margin.t + ")");
var xAxis = d3.svg.axis()
.scale(x)
.tickSubdivide(true)
.orient("bottom");
stacked.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + h + ")")
var yAxis = d3.svg.axis()
.scale(y)
.tickSubdivide(true)
.tickSize(-w1, 0, 0)
.orient("left");
var stack = d3.layout.stack()
.values(function(d) { return d.values; });
var area = d3.svg.area().interpolate("cardinal")
.x(function(d) { return x(d.year); })
.y0(function(d) { return y(d.y0); })
.y1(function(d) { return y(d.y + d.y0); })
stacked.append("g")
.attr("class", "y axis")
.call(yAxis);
// settings for donut chart
var radius = Math.min((w2), h) / 2,
labelRadius = radius - 20;
var krispy = d3.select("#pie").append("svg")
.attr("width", w2 + margin.r + margin.l)
.attr("height", h + margin.t + margin.b)
.append("g")
.attr("transform", "translate(150," + (h/2 + margin.t) + ")");
var arc = d3.svg.arc()
.outerRadius(radius - 15)
.innerRadius(radius - 55);
var pie = d3.layout.pie()
.sort(null)
.value(function(d) { return d.values; });
// bring in the data
d3.csv("us-historical-energy.csv", function(csv) {
// data variable that will be used throughout
data = csv;
// format dates
data.forEach(function(d) {
d.Year = formatTime(d.Year);
});
// function for adding data points one at a time
var latest = 1;
function update() {
// create array that will update with each new data point
dataChange = data.slice(0, latest)
latest++;
if (latest < csv.length) {
// redraw function draws the meat of the charts
redraw();
};
};
// update data every 500ms
var interval = setInterval(update, 500);
// create list energy sources to be used as keys
color.domain(d3.keys(data[0]).filter(function(key) { return key !== "Year" && key !== "sourcesPie"; }))
// create legend
var legend = stacked.append("g")
.attr("class", "legendBox")
var legends = legend.selectAll(".legend")
.data(color.domain())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(10," + (5 + (i * 20)) + ")"; });
legends.append("rect")
.attr("width", 15)
.attr("height", 15)
.style("fill", color)
legends.append("text")
.attr("x", 20)
.attr("y", 8)
.attr("dy", ".35em")
.text(function(d) { return d; });
// draw the charts
function redraw() {
// map vales to d3.layout.stack() for the area chart
var sourcesStack = stack(color.domain().map(function(name) {
return {
name: name,
values: data.map(function(d) {
return { year: d.Year, y: +d[name] };
})
};
}));
// set x domain to extend to the most recently added data point
x.domain([d3.min(dataChange, function(d) {
return d.Year; }),
d3.max(dataChange, function(d) {
return d.Year; })]);
// set data for energy sources stacked areas
var stacks = stacked.selectAll(".sources")
.data(sourcesStack);
// call enter() for stacked areas
var stacksEnter = stacks.enter().append("g")
.attr("class", "sources");
// draw paths and areas
stacksEnter.append("path")
.attr("class", "area")
.attr("d", function(d) { return area(d.values); })
.style("fill", function(d) { return color(d.name); });
// update and transition area values
var stacksUpdate = d3.transition(stacks)
stacksUpdate.transition().select("path").duration(500)
.attr("d", function(d) { return area(d.values); });
// update x axis
d3.selectAll(".x.axis").transition(stacked).duration(500).call(xAxis)
// create rect underlays that will be used for mouseovers
var underlay = stacks.selectAll(".underlay").data(data),
underlayWidth = w1/dataChange.length;
// enter() underlay g and append rects
var underlayEnter = underlay.enter().append("g")
.attr("class", "underlay");
underlayEnter.append("rect")
.attr("x", function(d, i) { return x(d.Year); })
.attr("width", underlayWidth)
.attr("y", 0)
.attr("height", h);
// update and move underlays; reduce width to svgwidth/data.length
var underlayUpdate = d3.transition(underlay);
underlayUpdate.transition().selectAll("rect").duration(500)
.attr("x", function(d, i) { return x(d.Year); })
.attr("width", underlayWidth);
// what to do when we mouse on or off a rect
underlay.on("mouseover", rectOn)
underlay.on("mouseout", rectOff)
// now for the donut
// map values to color.domain key
data.forEach(function(d) {
d.sourcesPie = color.domain().map(function(name) {
return {name: name, values: +d[name]};
});
});
// set data for the donut
var donut = krispy.selectAll(".arc")
.data(pie(dataChange[dataChange.length - 1].sourcesPie))
// enter() the donut "g"
var donutEnter = donut.enter().append("g")
.attr("class", "arc")
// things we will use to compute percentages
var total = d3.sum(dataChange[dataChange.length - 1].sourcesPie, function(d) { return d.values; })
var formatPercent = d3.format("%")
// draw donut arcs
donutEnter.append("path")
.attr("class", "donutPath")
.attr("d", arc)
.each(function(d) { this._current = d; })
.style("fill", function(d) { return color(d.data.name); })
// draw percentage labels inside arcs
donutEnter.append("text")
.attr("class", "donutLabels")
.attr("transform", function(d) {
return "translate(" + arc.centroid(d) + ")rotate(" + angle(d) + ")"; })
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.style("fill-opacity", function(d) {return d.value==0 ? 1e-6 : 1;})
.text(function(d) {
return formatPercent(d.data.values/total) });
// angle function used for rotating labels
function angle(d) {
var a = (d.startAngle + d.endAngle) * 90 / Math.PI - 90;
return a > 90 ? a - 180 : a;
}
// update and transition arcs and labels
var donutUpdate = d3.transition(donut);
donutUpdate.transition().select("text").duration(500)
.attr("transform", function(d) {
return "translate(" + arc.centroid(d) + ")rotate(" + angle(d) + ")"; })
.style("fill-opacity", function(d) {return d.value==0 ? 1e-6 : 1;})
.text(function(d) {
return formatPercent(d.data.values/total) });
donutUpdate.transition().select("path").duration(500)
.attrTween("d", arcTween)
function arcTween(a) {
var i = d3.interpolate(this._current, a);
this._current = i(0);
return function(t) {
return arc(i(t));
};
}
};
// helper functions
// what happens when we go on or off of a rect
var rectOn = function() {
var hoverRect = d3.select(this)
hoverRect.style("visibility", "visible")
}
var rectOff = function() {
var hoverRect = d3.select(this)
hoverRect.style("visibility", "hidden")
}
// stop animation when we roll over stacked area, restart when leaving
$('#stack').hover(function() {
clearInterval(interval);
},
function() {
interval = setInterval(update, 500);
});
});
</script>
</body>
</html>
Year,Biomass,Coal,Petroleum,Natural Gas,Captured Energy,Nuclear
1775,0.249,0,0,0,0,0
1785,0.31,0,0,0,0,0
1795,0.402,0,0,0,0,0
1805,0.537,0,0,0,0,0
1815,0.714,0,0,0,0,0
1825,0.96,0,0,0,0,0
1835,1.305,0,0,0,0,0
1845,1.757,0,0,0,0,0
1850,2.138,0.219,0,0,0,0
1855,2.389,0.421,0,0,0,0
1860,2.641,0.518,0.003,0,0,0
1865,2.767,0.632,0.01,0,0,0
1870,2.893,1.048,0.011,0,0,0
1875,2.872,1.44,0.011,0,0,0
1880,2.851,2.054,0.096,0,0,0
1885,2.683,2.84,0.04,0.082,0,0
1890,2.515,4.062,0.156,0.257,0.022,0
1895,2.306,4.95,0.168,0.147,0.09,0
1900,2.015,6.841,0.229,0.252,0.25,0
1905,1.843,10.001,0.61,0.372,0.386,0
1910,1.765,12.714,1.007,0.54,0.539,0
1915,1.688,13.294,1.418,0.673,0.659,0
1920,1.61,15.504,2.676,0.813,0.738,0
1925,1.533,14.706,4.28,1.191,0.668,0
1930,1.455,13.639,5.897,1.932,0.752,0
1935,1.397,10.634,5.675,1.919,0.806,0
1940,1.358,12.535,7.76,2.665,0.88,0
1945,1.261,15.972,10.11,3.871,1.442,0
1949,1.549262,11.980905,11.882722,5.145142,1.424722,0
1950,1.562307,12.347109,13.315484,5.968371,1.415411,0
1951,1.534669,12.552996,14.428043,7.048518,1.423795,0
1952,1.474369,11.306479,14.955682,7.549621,1.465812,0
1953,1.418601,11.372684,15.555829,7.906645,1.412859,0
1954,1.394327,9.714667,15.839176,8.330202,1.359772,0
1955,1.424143,11.167259,17.254955,8.997935,1.359844,0
1956,1.415871,11.349723,17.937473,9.613975,1.434711,0
1957,1.333581,10.820631,17.931667,10.190753,1.515613,0.000112
1958,1.323123,9.533287,18.526937,10.663199,1.591967,0.001915
1959,1.352874,9.518353,19.32265,11.717422,1.548465,0.002187
1960,1.31987,9.837785,19.91923,12.385366,1.608334,0.006026
1961,1.294762,9.623351,20.216387,12.926392,1.657464,0.019678
1962,1.300242,9.906454,21.048981,13.730841,1.817202,0.026394
1963,1.323316,10.412538,21.700828,14.403306,1.773115,0.038147
1964,1.336802,10.964385,22.301257,15.28785,1.888446,0.039819
1965,1.334761,11.580608,23.24568,15.768667,2.061055,0.043164
1966,1.368985,12.14308,24.400523,16.995332,2.063477,0.064158
1967,1.340249,11.91375,25.283661,17.944788,2.349964,0.088456
1968,1.419495,12.330677,26.979447,19.209656,2.353161,0.141534
1969,1.440487,12.38154,28.338336,20.677984,2.654405,0.153722
1970,1.430962,12.264528,29.520695,21.794707,2.639059,0.239347
1971,1.432323,11.598411,30.56129,22.469052,2.82989,0.412939
1972,1.503065,12.076917,32.946738,22.69819,2.878944,0.583752
1973,1.529068,12.97149,34.837435,22.512399,2.88187,0.910177
1974,1.539657,12.662878,33.45366,21.732488,3.20219,1.272083
1975,1.498734,12.662786,32.732323,19.947883,3.188386,1.899798
1976,1.713373,13.584067,35.177782,20.345426,3.013778,2.111121
1977,1.838332,13.922103,37.12398,19.930513,2.370634,2.701762
1978,2.037605,13.765575,37.962821,20.0004,2.967834,3.024126
1979,2.151906,15.039586,37.122274,20.665817,2.970948,2.775827
1980,2.4755,15.422809,34.20452,20.235459,2.952843,2.739169
1981,2.596283,15.907526,31.932206,19.747309,2.817406,3.007589
1982,2.663452,15.321581,30.232226,18.356222,3.316185,3.131148
1983,2.904414,15.894442,30.052216,17.220836,3.591198,3.202549
1984,2.971119,17.070622,31.053237,18.393613,3.466744,3.552531
1985,3.016233,17.478428,30.924732,17.703482,3.067784,4.075563
1986,2.932094,17.260405,32.19826,16.591364,3.179046,4.380109
1987,2.874884,18.008451,32.863733,17.639801,2.746923,4.753933
1988,3.016049,18.846312,34.222795,18.448393,2.440706,5.586968
1989,3.159358,19.069762,34.209296,19.601689,3.075876,5.602161
1990,2.73511,19.172635,33.551623,19.603168,3.305565,6.10435
1991,2.781798,18.99167,32.846032,20.032957,3.286719,6.422132
1992,2.931678,19.122471,33.524957,20.713632,2.889674,6.479206
1993,2.908172,19.835148,33.744546,21.228902,3.174333,6.410499
1994,3.027535,19.909463,34.560541,21.728065,2.960583,6.693877
1995,3.101142,20.088727,34.43837,22.671138,3.459341,7.075436
1996,3.156806,21.001914,35.67535,23.084647,3.856872,7.086674
1997,3.10522,21.445411,36.158897,23.222717,3.910322,6.596992
1998,2.927489,21.655744,36.815915,22.830226,3.565409,7.067809
1999,2.963291,21.622544,37.837705,22.909227,3.552327,7.610256
2000,3.008228,22.579528,38.261705,23.823978,3.098124,7.862349
2001,2.622347,21.914268,38.18551,22.772558,2.540203,8.028853
2002,2.700598,21.903989,38.224147,23.510081,3.028521,8.145429
2003,2.807132,22.320928,38.811443,22.830642,3.176232,7.958858
2004,3.009666,22.466195,40.29178,22.923061,3.072751,8.221985
2005,3.116765,22.796543,40.388116,22.565364,3.125178,8.16081
2006,3.266757,22.44716,39.955351,22.238738,3.382414,8.215414
2007,3.474262,22.749466,39.773964,23.662759,3.048323,8.455364
2008,3.848548,22.385196,37.279917,23.842954,3.337857,8.427297
2009,3.9117,19.692203,35.403266,23.41594,3.687903,8.356019
2010,4.294066,20.84952,36.009541,24.256183,3.795848,8.434433
2011,4.411164,19.643039,35.282604,24.842548,4.724236,8.259432