|
<!DOCTYPE html> |
|
<head> |
|
<meta charset="utf-8"> |
|
<script src="https://d3js.org/d3.v4.min.js"></script> |
|
<style> |
|
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; } |
|
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; } |
|
.xAxisText, .yAxisText{font-size: 30} |
|
.popObj {} |
|
.outerGroup {} |
|
.popObj1990 {} |
|
.popObj1991 {} |
|
.popObj1992 {} |
|
.popObj1993 {} |
|
.popObj1994 {} |
|
.popObj1995 {} |
|
.popObj1996 {} |
|
.popObj1997 {} |
|
.popObj1998 {} |
|
.popObj1999 {} |
|
.popObj2000 {} |
|
.popObj2001 {} |
|
.popObj2002 {} |
|
.popObj2003 {} |
|
.popObj2004 {} |
|
.popObj2005 {} |
|
.popObj2006 {} |
|
.popObj2007 {} |
|
.popObj2008 {} |
|
.popObj2009 {} |
|
.popObj2010 {} |
|
.popObj2011 {} |
|
.popObj2012 {} |
|
.popObj2013 {} |
|
.popGroup {} |
|
.stem1990 {} |
|
.stem1991 {} |
|
.stem1992 {} |
|
.stem1993 {} |
|
.stem1994 {} |
|
.stem1995 {} |
|
.stem1996 {} |
|
.stem1997 {} |
|
.stem1998 {} |
|
.stem1999 {} |
|
.stem2001 {} |
|
.stem2002 {} |
|
.stem2003 {} |
|
.stem2004 {} |
|
.stem2005 {} |
|
.stem2006 {} |
|
.stem2007 {} |
|
.stem2008 {} |
|
.stem2009 {} |
|
.stem2010 {} |
|
.stem2011 {} |
|
.stem2012 {} |
|
.stem2013 {} |
|
|
|
.floatingLabel {} |
|
.Year {} |
|
|
|
|
|
|
|
.textMarker{} |
|
|
|
|
|
|
|
#chart { |
|
position: fixed; |
|
left: 0px; |
|
right: 0px; |
|
top: 0px; |
|
bottom: 0px; |
|
} |
|
|
|
|
|
|
|
.tooltip{ |
|
position: absolute; |
|
text-align: center; |
|
width: 60px; |
|
height: 28px; |
|
padding: 2px; |
|
font: 12px sans-serif; |
|
background: lightsteelblue; |
|
border: 0px; |
|
border-radius: 8px; |
|
pointer-events: none; |
|
} |
|
|
|
#chart { |
|
position: fixed; |
|
left: 0px; |
|
right: 0px; |
|
top: 0px; |
|
bottom: 0px; |
|
} |
|
|
|
|
|
|
|
|
|
</style> |
|
|
|
|
|
|
|
|
|
</head> |
|
|
|
<body> |
|
|
|
|
|
<div id="chart"></div> |
|
|
|
<script> |
|
|
|
|
|
|
|
|
|
//var height = 500; |
|
//var width = 960; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var chartDiv = document.getElementById("chart"); |
|
var svg = d3.select('div').selectAll('svg').data([null]); |
|
svg = svg.enter().append('svg'); |
|
|
|
function render(data, year, countryNum) |
|
{ |
|
|
|
|
|
data = data.filter(function(d){return(d.Year <= Math.ceil(year));}); |
|
data = data.filter(function(d){return(d.Final_Rank <= countryNum)}); |
|
data = data.sort(function(a,b){return(a.Final_Rank - b.Final_Rank);}) |
|
|
|
var height = chartDiv.clientHeight; |
|
var width = chartDiv.clientWidth; |
|
var heightF = function(){return(chartDiv.clientHeight);} |
|
var widthF = function(){return(chartDiv.clientWidth);} |
|
|
|
|
|
|
|
|
|
var margin = {top: 100, bottom: 40, left:80, right:20}; |
|
var innerHeight = height - margin['top'] - margin['bottom']; |
|
var innerWidth = width - margin['left'] - margin['right']; |
|
|
|
|
|
|
|
|
|
|
|
|
|
var colorScale = d3.scaleOrdinal().range(d3.schemeCategory10); |
|
|
|
var xValue = d => d.Country;//function(d){return d.Country;} |
|
var xScale = d3.scaleBand().padding(.80); |
|
xScale.domain(data.map(xValue)) |
|
.range([0,innerWidth/2]); |
|
|
|
var yScale = d3.scaleLinear().domain([0,160000]) |
|
.range([innerHeight,0]); |
|
|
|
|
|
var yValueBottom = d => d.GHG_Cum - d.GHG; |
|
var yValueTop = d => d.GHG_Cum |
|
|
|
|
|
//Insert SVG element |
|
|
|
svg = svg.merge(svg) |
|
.attr('height', height) |
|
.attr('width', width); |
|
|
|
svg.exit().remove(); |
|
|
|
//var graphTitle = svg.selectAll('text').data([null]); |
|
|
|
var graphTitle = svg.selectAll('.graphTitle').data([null]); |
|
graphTitle = graphTitle.enter().append('text') |
|
.attr('class', 'graphTitle') |
|
.merge(graphTitle) |
|
.text(Math.ceil(year)) |
|
.attr("y", height/2) |
|
.attr("x", width/5) |
|
.attr("font-size", height/15) |
|
.attr("font-family", "monospace") |
|
.attr('stroke', 'black'); |
|
|
|
graphTitle.exit().remove(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var mainGraphGroup = svg.selectAll('.outerGroup').data([null]); |
|
|
|
|
|
mainGraphGroup = mainGraphGroup.enter() |
|
.append('g') |
|
.attr('class', 'outerGroup') |
|
.merge(mainGraphGroup) |
|
.attr('height', innerHeight) |
|
.attr('width', innerWidth) |
|
.attr('transform', `translate(${margin['left']}, ${margin['top'] -100})`); |
|
|
|
mainGraphGroup.exit().remove(); |
|
|
|
//console.log(mainGraphGroup.attr('height')); |
|
|
|
|
|
|
|
|
|
|
|
var xAxisG = mainGraphGroup.selectAll('.xAxisG').data([null]); |
|
//xAxisG.attr('transform', `translate(0,${innerHeight})`); |
|
|
|
xAxisG = xAxisG.enter() |
|
.append('g') |
|
.attr('class', 'xAxisG') |
|
.merge(xAxisG) |
|
.attr('transform', `translate(0,${innerHeight})`); |
|
|
|
xAxisText = xAxisG.selectAll('text').data([null]); |
|
|
|
xAxisText.enter() |
|
.append('text') |
|
.merge(xAxisText) |
|
.text('Country') |
|
.attr('stroke', 'black') |
|
.attr('transform',`translate(${innerWidth/2},${innerHeight/(10)})`); |
|
|
|
|
|
xAxisG.exit().remove(); |
|
|
|
var xAxis = d3.axisBottom(xScale); |
|
|
|
|
|
|
|
|
|
|
|
var yAxisG =mainGraphGroup.selectAll('.yAxisG').data([null]); |
|
yAxisG = yAxisG.enter().append('g') |
|
.attr('class', 'yAxisG') |
|
.merge(yAxisG); |
|
|
|
|
|
|
|
|
|
var yAxisText = yAxisG.selectAll('text').data([null]); |
|
yAxisText.enter().append('text') |
|
.merge(yAxisText) |
|
.text('GHG emissions (tonnes)') |
|
.attr('stroke','black') |
|
.attr('transform', `rotate(-90)`) |
|
.attr('x',-innerHeight/1.5) |
|
.attr('y', -innerHeight/20); |
|
|
|
|
|
yAxisG.exit().remove(); |
|
|
|
|
|
var yAxis = d3.axisLeft(yScale); |
|
|
|
|
|
|
|
var topYear = Math.max(Math.min(2013, Math.ceil(year)), 1990); |
|
var linkData = data.filter(function(d){return(d.Year == topYear);}); |
|
|
|
//console.log(linkData); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var fYearData = data.filter(function(d){return(d.Year == year);}) |
|
|
|
//console.log(fYearData); |
|
|
|
var factor = 1 - (Math.ceil(year) - year); |
|
//console.log(factor) |
|
|
|
|
|
|
|
|
|
var popObj = mainGraphGroup.selectAll('.popObj').data(fYearData) |
|
.attr('transform', function(d){return( |
|
'translate('+ (xScale(d.Country)+ xScale.bandwidth()/2) + ',' + yScale(d.GHG_Cum - d.GHG + factor * d.GHG) + ')');}) |
|
|
|
|
|
//var popObjUpdate = popObj.append('circle') |
|
// .attr('r',30); |
|
|
|
var popObjEnter = popObj.enter() |
|
.append('g') |
|
.attr('class', 'popObj') |
|
.attr('transform', function(d){return( |
|
'translate('+ (xScale(d.Country)+ xScale.bandwidth()/2) + ',' + yScale(d.GHG_Cum - d.GHG + factor * d.GHG) + ')');}) |
|
var popCircle = popObjEnter |
|
.append('circle') |
|
.attr("r",d => Math.sqrt(d.Population/(1000000))) |
|
.attr("fill", "rgba(10, 10, 10,.1)"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*popObjEnter = popObjEnter.merge(popObj) |
|
.attr('transform', function(d){return( |
|
'translate('+ (xScale(d.Country)+ xScale.bandwidth()/2) + ',' + yScale(d.GHG_Cum - d.GHG + factor * d.GHG) + ')');});;*/ |
|
|
|
//popObj.append('circle') |
|
// .attr('r', 30); |
|
; |
|
|
|
/* //.attr('transform', function(d){return( |
|
// 'translate('+ (xScale(d.Country)+ xScale.bandwidth()/2) + ',' + yScale(d.GHG_Cum - d.GHG + factor * d.GHG) + ')');}); |
|
popObj.select('circle') |
|
.attr("r",d => Math.sqrt(d.Population/(1000000))) |
|
.attr("fill", "rgba(10, 10, 10,.1)") |
|
.attr('cx',0) |
|
.attr('cy',0); |
|
|
|
popObjEnter.append('circle'); |
|
|
|
popObj = popObj.merge(popObj) |
|
.attr('stroke-dasharray', '5,5') |
|
.attr('transform', function(d){return( |
|
'translate('+ (xScale(d.Country)+ xScale.bandwidth()/2) + ',' + yScale(d.GHG_Cum - d.GHG + factor * d.GHG) + ')');}) |
|
.attr('stroke', 'black') |
|
.select('circle') |
|
.attr('transform', 'translate(0,0)') |
|
//.selectAll('circle') |
|
//.attr("r",d => Math.sqrt(d.Population/(1000000))) |
|
// .attr("fill", "rgba(10, 10, 10,.1)"); |
|
; |
|
|
|
popObj = popObj.on('mouseover', function(d){ |
|
d3.select(this).select('circle').attr('fill', 'rgba(0,0,255,.2)'); |
|
d3.select(this).select('text') |
|
.text(d => "Pop: " + Math.round(d.Population/1000000) + "M , Cum GHG: " + Math.round(d.GHG_Cum/1000) + 'K tonnes') |
|
.attr('y',-40) |
|
.attr('x', 50) |
|
.style('display',null); |
|
|
|
//var thisYear = d3.select(this).attr('cx'); |
|
//console.log(d3.select(this).data()[0]); |
|
|
|
|
|
|
|
|
|
}) |
|
.on('mouseout', function(d){ |
|
//d3.select(this).select('circle').attr('fill', 'rgba(10, 10, 10, .1)'); |
|
|
|
d3.select(this).select('circle').attr('fill', 'rgba(10, 10, 10, .1)'); |
|
d3.select(this).select('text').style('display','none'); |
|
}) |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*popObj |
|
.append('circle') |
|
.attr("r",d => Math.sqrt(d.Population/(1000000))) |
|
.attr("fill", "rgba(10, 10, 10,.1)");*/ |
|
|
|
popObj.exit().selectAll('circle').remove(); |
|
popObj.exit().remove(); |
|
//popCircle.exit().remove(); |
|
|
|
|
|
|
|
var countryData = data.filter(function(d){return(d.Year == year);}); |
|
countryData = countryData.sort(function(a,b){return a.Year - b.Year;}) |
|
|
|
|
|
var yScaleSide = d3.scaleLinear().domain([0,12000]) |
|
.range([innerHeight/2.5,0]); |
|
|
|
var xScaleSide = d3.scaleLinear().domain([1990, 2013]) |
|
.range([0,innerWidth/2.5]); |
|
|
|
|
|
var line = d3.line() |
|
.curve(d3.curveLinear) |
|
.x(function(d){ |
|
return xScaleSide(d.Year);}) |
|
.y(function(d){ return yScaleSide(d.GHG); }); |
|
|
|
|
|
|
|
|
|
|
|
var sideVizG = mainGraphGroup.selectAll('.sideVizG').data([null]); |
|
sideVizG = sideVizG.enter().append('g') |
|
.attr('class', 'sideVizG') |
|
.merge(sideVizG) |
|
.attr('transform', `translate(${innerWidth/1.75}, ${innerHeight/10.0})`); |
|
sideVizG.exit().remove(); |
|
|
|
|
|
var xAxisGLine = sideVizG.selectAll('.xAxisLine').data([null]); |
|
xAxisGLine = xAxisGLine.enter() |
|
.append('g') |
|
.attr('class', 'xAxisLine') |
|
.merge(xAxisGLine) |
|
.attr('transform', `translate(${0},${innerHeight/2.5})` ); |
|
|
|
var xAxisGLineText = xAxisGLine.selectAll('text').data([null]); |
|
xAxisGLineText = xAxisGLineText.enter() |
|
.append('text') |
|
.text('Year') |
|
.attr('stroke','black') |
|
.attr('transform',`translate(${innerWidth/4.5},30)`); |
|
|
|
xAxisGLine.exit().remove(); |
|
var xAxisLine = d3.axisBottom(xScaleSide); |
|
|
|
var yAxisGLine = sideVizG.selectAll('.yAxisGLine').data([null]); |
|
yAxisGLine = yAxisGLine.enter().append('g') |
|
.attr('class', 'yAxisGLine') |
|
.merge(yAxisGLine); |
|
|
|
|
|
|
|
var yAxisGLineText = yAxisGLine.selectAll('text').data([null]); |
|
yAxisGLineText = yAxisGLineText.enter() |
|
.append('text') |
|
.text('GHG emissions (tonnes)') |
|
.attr('stroke','black') |
|
.attr('transform', `rotate(-90)`) |
|
.attr('x',-innerHeight/20) |
|
.attr('y', -45); |
|
|
|
|
|
|
|
|
|
yAxisGLine.exit().remove(); |
|
|
|
var yAxisLine = d3.axisLeft(yScaleSide); |
|
|
|
|
|
//var countryLine = {} |
|
|
|
var pivoter = function(arr, key) |
|
{ |
|
var output = {'Country':key} |
|
console.log(key,"YYYYYYYYYYY") |
|
for(var i in arr) |
|
{ |
|
//console.log(i) |
|
if(arr.hasOwnProperty(i)) |
|
{output[arr[i]['key']] = arr[i]['value'];} |
|
} |
|
return(output) |
|
}; |
|
|
|
var pivotWrapper = function(arr) |
|
{ |
|
return(pivoter(arr['values'], arr['key'])) |
|
|
|
} |
|
|
|
var countryLine = d3.nest() |
|
.key(function(d){return(d.Country);}) |
|
.key(function(d){return(d.Year);}) |
|
.sortKeys(d3.descending) |
|
.rollup(function(v){return d3.sum(v, function(d){return d.GHG;})}) |
|
.entries(data); |
|
//.object(function(d){return d.GHG;}); |
|
|
|
console.log(pivotWrapper(countryLine[0])); |
|
|
|
|
|
|
|
//////////Have this respond to resize/////////////////// |
|
/*for(var datum = 0; datum < countryData.length; datum++) |
|
{ |
|
var thisCountryData = data.filter(function(d){return(d.Country == countryData[datum].Country);}); |
|
thisCountryData = thisCountryData.sort(function(a,b){return(a.Year - b.Year);}); |
|
var thisCountry = thisCountryData[0].Country; |
|
|
|
|
|
|
|
|
|
countryLine[thisCountry] = sideVizG.append('path').datum(thisCountryData) |
|
.attr('class','line') |
|
.style('stroke', function(d){return colorScale(thisCountry);}) |
|
.style('fill','none') |
|
.attr("d",line);//.attr('stroke','black'); |
|
|
|
|
|
|
|
|
|
};*/ |
|
////////////////////////////////////////////////////// |
|
|
|
var bandwidthFactor = 1.08 |
|
var stemObjBottom = {}; |
|
for(var yr = 1990; yr <= year; yr++) |
|
{ |
|
stemObjBottom[yr] = mainGraphGroup.selectAll('.stem' + yr).data([null]); |
|
stemObjBottom[yr] = stemObjBottom[yr].enter().append('g') |
|
.attr('class','stem' + yr) |
|
.merge(stemObjBottom[yr]) |
|
|
|
|
|
stemObjBottom[yr].exit().remove(); |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
//StartHere |
|
for(var yr = 1990; yr <= year; yr++) |
|
{ |
|
|
|
var yearData = data.filter(function(d){return(d.Year == yr);}) |
|
|
|
var circleObjs = stemObjBottom[yr].selectAll('circle').data(yearData); |
|
circleObjs =circleObjs.enter().append('circle') |
|
.merge(circleObjs) |
|
.attr('r',3) |
|
//.attr('fill','rgba(0,0,0,.2)') |
|
.attr('fill', function(d){return colorScale(d.Country);}) |
|
.attr('cx',d => xScale(xValue(d)) + xScale.bandwidth()/2) |
|
.attr('cy', d =>{return yScale(d.GHG_Cum);}); |
|
|
|
|
|
|
|
circleObjs.exit().remove(); |
|
|
|
var linkObj = stemObjBottom[yr].selectAll('.link').data(yearData); |
|
linkObj = linkObj.enter() |
|
.append('line') |
|
.attr('class', 'link') |
|
.merge(linkObj) |
|
.attr('x1',function(d){return(xScale(d.Country) + xScale.bandwidth()/2);}) |
|
.attr('x2',function(d){return(xScale(d.Country) + xScale.bandwidth()/2);}) |
|
.attr('y1', function(d){return(yScale(d.GHG_Cum));}) |
|
.attr('y2', function(d){return(yScale(d.GHG_Cum - d.GHG));}) |
|
.attr('stroke-dasharray', '5,4') |
|
.attr('stroke', 'black') |
|
.attr('stroke', function(d){return colorScale(d.Country);}) |
|
.attr('stroke-width', 1); |
|
|
|
|
|
stemObjBottom[yr].on('mouseover',function(d){ |
|
var className = "stem" + yr |
|
d3.select(this).selectAll('circle') |
|
//.attr("fill", "blue") |
|
.attr('r',6); |
|
|
|
d3.select(this).selectAll('line') |
|
.attr('stroke-width', 3) |
|
//.attr('stroke', 'blue') |
|
.attr('stroke-dasharray','none'); |
|
//.attr('r',d=>{return(Math.sqrt(d.Population/(1000000)));}) |
|
|
|
|
|
|
|
var tempData = d3.select(this).selectAll('circle').data(); |
|
|
|
|
|
}) |
|
.on('mouseout',function(d){ |
|
var className = "stem" + yr; |
|
var country = d3.select(this).selectAll('circle').data(); |
|
//console.log(country); |
|
//var color = colorScale(d3.select(this).data().Country); |
|
|
|
d3.select(this).selectAll('circle') |
|
//.attr('fill', function(d){return(colorScale(d.Country));}) |
|
//.attr("fill", 'rgba(0,0,0,.2)') |
|
.attr('r',3); |
|
d3.select(this).selectAll('line') |
|
.attr('stroke-width', 1) |
|
//.attr('stroke', 'black') |
|
//.attr('stroke',color) |
|
.attr('stroke-dasharray', '5,4'); |
|
|
|
|
|
|
|
}) |
|
stemObjBottom[yr].exit().remove(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
xAxisG.call(xAxis) |
|
.selectAll('.tick text') |
|
.attr('transform','rotate(-45)'); |
|
|
|
yAxisG.call(yAxis) |
|
.selectAll('tick text') |
|
.attr('stroke', 'black'); |
|
xAxisGLine.call(xAxisLine) |
|
.selectAll('.tick text') |
|
.attr('transform','rotate(-45)'); |
|
|
|
yAxisGLine.call(yAxisLine); |
|
|
|
svg.exit().remove(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var rows = function(d){ |
|
d.Country = d.Country; |
|
d.Year = +d.Year; |
|
d.GHG = +d.GHG; |
|
d.GHG_Cum = +d.GHG_Cum; |
|
d.Population = +d.Population; |
|
d.Final_Rank = +d.Final_Rank; |
|
return(d);}; |
|
|
|
//d3.csv("Data3.csv", rows , function(data){return(render(data, 2013, 10))}) |
|
|
|
var redraw = function() |
|
{ |
|
d3.csv("Data3.csv", rows,function(data){return(render(data, 2013, 10));}); |
|
}; |
|
|
|
redraw(); |
|
window.addEventListener("resize", redraw); |
|
|
|
</script> |
|
</body> |