Built with blockbuilder.org
forked from RobertDelgado's block: Project Prototype round 3
xxxxxxxxxx
<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 {}
.Year {}
.textMarker{}
.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;
}
</style>
</head>
<body>
<p>
<label for="Year" style="display: inline-block; width: 160px; text-align: right">
Year = <span id="Year-value" style="width:400px">…</span>
</label>
<input type="range" min="1990" max="2013" id="Year">
</p>
<script>
var height = 500;
var width = 960;
var margin = {top: 50, bottom: 40, left:20, right:20};
var innerHeight = height - margin['top'] - margin['bottom'];
var innerWidth = height - margin['left'] - margin['right'];
function generalUpdate(obj, elt, data)
{
var className = ((elt.hasOwnProperty('cl'))? elt.class: elt.obj);
var output = obj.selectAll(className)
.data(data);
return(output)
};
function generalEnter(obj, elt)
{
var output = obj.enter().append(elt.obj);
if(elt.hasOwnProperty('cl'))
output = output.attr('class', elt.cl);
return(output)
};
function attributes(obj, attributes)
{
var output = obj;
for(var name in attributes)
{
if( attributes.hasOwnProperty(name))
{
output = output.attr(name, attributes[name]);
};
};
return(output);
}
/*function exitObjects(arr)
{
for(name in arr)
{
if(arr.hasOwnProperty(name))
{
arr[name].exit().remove();
}
}
}*/
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 xValue = d => d.Country;//function(d){return d.Country;}
var xScale = d3.scaleBand().padding(.80);
xScale.domain(data.map(xValue))
.range([0,innerWidth]);
//var yScale = d3.scaleLinear().domain([0,d3.max(data, d => d.GHG_Cum) + 1000])
// .range([innerHeight,0]);
var yScale = d3.scaleLinear().domain([0,200000])
.range([innerHeight,0]);
var yValueBottom = d => d.GHG_Cum - d.GHG;
var yValueTop = d => d.GHG_Cum
var body = d3.select('body');
var svg = generalUpdate(body, {obj:'svg'}, [null]);
svg = attributes(svg,{height:height,width:width} );
svg = generalEnter(svg, {obj: 'svg'} ); //Why do I need this here and not after svg declaration?
svg = attributes(svg,{height:innerHeight,width:innerWidth} );
var outerGroup = generalUpdate(svg, {obj: 'g'}, [null]);
outerGroup = generalEnter(outerGroup, {obj: 'g', cl:'.outerGroup'});
outerGroup = attributes(outerGroup, {height: innerHeight
, width: innerWidth
, transform: `translate(${margin['left']}, ${margin['top']})`});
outerGroup = outerGroup.merge(outerGroup);
var floatingLabel = generalUpdate(outerGroup, {obj:'g', cl:'.floatingLabel'}, [null]);
var fYearData = data.filter(function(d){return(d.Year == Math.ceil(year));})
//console.log(fYearData)
var factor = 1 - (Math.ceil(year) - year);
//console.log(factor)
var popObj = generalUpdate(outerGroup, {obj:"g", cl:".popObj"}, fYearData);
popObj = generalEnter(popObj, {obj:"g", cl:".popObj"})
popObj = popObj.merge(popObj);
popObj = attributes(popObj,{transform: function(d){return(
'translate('+ (xScale(d.Country)+ xScale.bandwidth()/2) + ',' + yScale(d.GHG_Cum - d.GHG + factor * d.GHG) + ')');}
, stroke: "black"
, 'stroke-dasharray': '5,5'}
);
popCircle = popObj.append('circle')
.attr("r",d => Math.sqrt(3*d.Population/(1000000)))
.attr("fill", "rgba(10,10,10,.1)")
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);
})
.on('mouseout', function(d){
d3.select(this).select('circle').attr('fill', 'rgba(10, 10, 10, .1)');
d3.select(this).select('text').style('display','none');
})
;
popObj = popObj.append('text')
.text('Hello')
.style('display','none');
popObj.exit().remove();
floatingLabel = generalEnter(floatingLabel, {obj:'g', cl:'.floatingLabel'});
floatingLabel = floatingLabel.style("display", "none");
floatingLabel.append('rect')
.attr("width",60)
.attr("height", 20)
.attr("fill", "white")
.attr("opacity", .5);
floatingLabel.exit().remove();
var floatingText = floatingLabel.append("text")
.attr("x", 30)
.attr("dy", "1.2em")
.style("text-anchor", "middle")
.attr("font-size", "12px")
.attr("font-weight", "bold");
var popMarker = floatingText.append('tspan');
var cumGHGMarker = floatingText.append('tspan');
var bandwidthFactor = 1.08
var stemObjBottom = {}
for(var yr = 1990; yr < year; yr++)
{
yearData = data.filter(function(d){return(d.Year == yr);})
stemObjBottom[yr] = generalUpdate(outerGroup,{obj:"rect", cl:".stem" + yr}, yearData);
stemObjBottom[yr] = generalEnter(stemObjBottom[yr],{obj:"rect", cl:".stem" + yr});
stemObjBottom[yr] = stemObjBottom[yr].merge(stemObjBottom[yr]);
stemObjBottom[yr] = attributes(stemObjBottom[yr], {height:function(d){return( innerHeight - yScale(d.GHG));}
, width: xScale.bandwidth() * bandwidthFactor
, stroke:"black"
, x: d => xScale(xValue(d))
, y: function(d){return yScale(d.GHG_Cum - d.GHG);}
, fill:"none"});
stemObjBottom[yr] = stemObjBottom[yr].on('mouseover',function(d){
//d3.select(this).attr("fill","blue");
var className = "stem" + yr
var currentClass = d3.select(this).attr('class');
console.log(currentClass);
outerGroup.selectAll(currentClass).attr("fill", "blue");
})
stemObjBottom[yr].exit().remove();
};
var stemObjTop = generalUpdate(outerGroup,{obj:"rect", cl:".stem" + Math.ceil(year)}, fYearData);
stemObjTop = generalEnter(stemObjTop, {obj:"rect", cl:".stem" + Math.ceil(year)});
stemObjTop = stemObjTop.merge(stemObjTop);
stemObjTop = attributes(stemObjTop, {width: xScale.bandwidth() * bandwidthFactor
, height:function(d){return(yScale( (1-factor) * d.GHG));}
, x: d=>xScale(xValue(d))
, y: function(d){return(yScale((d.GHG_Cum - d.GHG) + factor * d.GHG ));}
, stroke: "black"
, fill: "none"});
stemObjTop.exit().remove();
/*var popObj = generalUpdate(outerGroup, {obj:"g", cl:".popObj"}, fYearData);
popObj = generalEnter(popObj, {obj:"g", cl:".popObj"})
popObj = popObj.merge(popObj);
popObj = attributes(popObj,{transform: function(d){return(
'translate('+ (xScale(d.Country)+ xScale.bandwidth()/2) + ',' + yScale(d.GHG_Cum - d.GHG + factor * d.GHG) + ')');}
, stroke: "black"
, 'stroke-dasharray': '5,5'}
);*/
}
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, 2))})
/*var update = function(Year){
console.log(Year);
d3.csv("Data3.csv", rows , function(data){return(render(data, Year, 5))});
};
//d3.csv("Data3.csv", rows , function(data){return(render(data, 2013, 2))})
update(1990)
d3.select("#Year").on("input", function()
{
update(+this.value);
});*/
</script>
</body>
https://d3js.org/d3.v4.min.js