Built with blockbuilder.org
forked from RobertDelgado's block: Refactor Project
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/d3-tip/0.6.3/d3-tip.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/d3-legend/1.1.0/d3-legend.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
.topMarks {}
.topMarks1990 {}
.topMarks1991 {}
.topMarks1992 {}
.topMarks1993 {}
.topMarks1994 {}
.topMarks1995 {}
.topMarks2001 {}
.bottomMarks {}
.bottomMarks1990 {}
.bottomMarks1991 {}
.bottomMarks2001 {}
.bottomMarks:hover{stroke:gray; stroke-width:.15em;}
.connectingMarks {}
.connectingMarks1990 {}
.connectingMarks2001 {}
.annotation{}
.xAxis, .yAxis {}
.xAxis1990, .yAxis1990 {}
.xAxis2001, .yAxis2001 {}
.floatingLabel {}
.floatingLabel1990 {}
.floatingLabel2001{}
.graphContainer {}
.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>
<script>
// Feel free to change or delete any of the code you see in this editor!
var height = 500;
var width = 10000;
var margin = {top: 20, bottom: 20, left:50, right:20};
var innerHeight = height - margin['top'];
var innerWidth = height - margin['left'];
function generalUpdate(obj, elt, data, attributes)
{
var className = ((elt.hasOwnProperty('cl'))? elt.class: elt.obj);
var output = obj.selectAll(className)
.data(data);
return(output)
};
function generalEnter(obj, elt, attributes)
{
var output = obj.enter().append(elt.obj);
if(elt.hasOwnProperty('class'))
output = output.attr('class', elt.class);
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 render(data)
{
var graphWidth = 200
var graphHeight = 200
var xValue = d => d.Country;//function(d){return d.Country;}
var xScale = d3.scaleBand().padding(.90);
xScale.domain(data.map(xValue))
.range([0,graphWidth]);
var yScale = d3.scaleLinear().domain([0,d3.max(data, d => d.GHG_Cum) + 1000])
.range([graphHeight,0]);
//console.log(data);
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], {height:height,width:width});
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:height,width:width} );
var exitFunct = function(objs)
{
for(name in objs)
{
if(objs.hasOwnProperty(name))
{
objs[name].exit().remove();
}
}
}
var makeChart = function(data, year1, translateString)
{
var numberOfCountries = 10;
data = data.filter(function(d){return d.Year == year1; });
data = data.filter(function(d){return d.Final_Rank <= numberOfCountries;});
data = data.sort(function(x,y){return(x.Final_Rank - y.Final_Rank);});
var floatingLabel = svg
.selectAll('.floatingLabel' + year1)
.data([null]);
floatingLabel = floatingLabel.enter()
.append('g')
.attr("class", "floatingLabel" + year1)
.style("display", "none");
floatingLabel.append("rect")
.attr("width", 60)
.attr("height", 20)
.attr("fill", "white")
.style("opacity", .5);
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 group = generalUpdate(svg, {obj:'g', cl: '.graphContainer'},[null]);
group = attributes(group, {height:graphHeight
, width: graphWidth
, transform:translateString})
//`translate(${margin['left']}, ${margin['top'] -10})` });
group = generalEnter(group, {obj: 'g'}, {height:graphHeight
, width: graphWidth
, transform:translateString});
group = attributes(group, {height:graphHeight
, width: graphWidth
, transform: translateString});
var annotation = generalUpdate(group, {cl: '.annotation', obj:'text'}, [null]);
annotation = generalEnter(annotation, {cl: '.annotation', obj:'text'});
annotation = annotation.text(year1);
annotation = attributes(annotation, {
stroke: 'black'
, transform: 'translate(100, 100)'
, "font-size": '1.5em'
, fill: 'white'}
);
var topMarks = generalUpdate(group, {cl: ".topMarks"+year1, obj: "circle"}, data);
topMarks = generalEnter(topMarks,{cl: ".topMarks" + year1, obj: "circle"});
topMarks = topMarks.merge(topMarks);
topMarks = attributes(topMarks,{cx: function(d){return xScale(xValue(d)) + xScale.bandwidth()/2;}
, cy: function(d){return yScale(yValueTop(d));}
, r: function(d){return Math.sqrt(height * d.Population/(1000000*600));}
, fill: 'rgba(255,123,50,.2)'
} );
///For interactivity. I may modularize this
topMarks = topMarks.on("mouseover", function() { floatingLabel.style("display", null); })
.on("mouseout", function() { floatingLabel.style("display", "none"); })
.on("mousemove", function(d) {
//console.log(d);
var thisX = d3.mouse(this)[0];
var thisY = d3.mouse(this)[1];
var yOffset = (thisY < 100 ? -5 : -50 )
console.log(yOffset, thisY, yScale(1000000000));
var xPosition = thisX + 200;
var yPosition = thisY + yOffset;
floatingLabel.attr("transform", "translate(" + xPosition + "," + yPosition + ")");
popMarker.text("Pop (M): " + d.Population/1000000).attr("x", "0").attr("dy", "1.2em");
cumGHGMarker.text("Cum Emiss: " + d.GHG_Cum).attr("x", "0").attr("dy", "1.2em");
});
var bandwidth = xScale.bandwidth();
var connectingMarks = generalUpdate(group, {cl: '.connectingMarks' + year1, obj: 'rect'}, data);
connectingMarks = generalEnter(connectingMarks, {cl: '.connectingMarks' + year1, obj: 'rect'} );
connectingMarks = connectingMarks.merge(connectingMarks);
connectingMarks = attributes(connectingMarks, {x:function(d){return xScale(xValue(d));}
,y:function(d){return yScale(yValueTop(d));}
, width: function(d){return xScale.bandwidth()*2.5;}
, height: function(d){return graphHeight - yScale(yValueTop(d) - yValueBottom(d));}});
var bottomMarks = generalUpdate(group, {cl:'.bottomMarks' + year1, obj: 'line'}, data);
bottomMarks = generalEnter(bottomMarks, {cl:'.bottomMarks' + year1, obj: 'line'} );
bottomMarks = bottomMarks.merge(bottomMarks);
bottomMarks = attributes(bottomMarks, {
x1: function(d){return(xScale(xValue(d)) + bandwidth/2);}
, x2: function(d){return(xScale(xValue(d)) + bandwidth/2);}
, y1: function(d){return yScale(yValueBottom(d));}
, y2: function(d){return yScale(1500) ;}
, stroke: 'black'
, 'stroke-dasharray': '5,2'
});
var xAxisG = generalUpdate(group, {obj: 'g', cl: '.xAxis' + year1}, [null]);
xAxisG = generalEnter(xAxisG, {obj: 'g', cl: '.xAxis' + year1});
xAxisG = xAxisG.style('font-size', '7px').style('font', 'Times').merge(xAxisG);
xAxisG = attributes(xAxisG, {'transform':`translate(0, ${yScale(graphHeight)})`});
var xAxis = d3.axisBottom()
.scale(xScale)
.ticks(5)
.tickSize(width/50 + ' em');
var yAxisG = generalUpdate(group, {obj: 'g', cl: '.yAxis'}, [null]);
yAxisG = generalEnter(yAxisG, {obj: 'g', cl: '.yAxis'});
yAxisG = yAxisG.style('font-size', '15px').style('font', 'Helvetica').merge(yAxisG);
yAxisG = attributes(yAxisG, {'transform':`translate(${xScale(0)},0)`});
var yAxis = d3.axisLeft()
.scale(yScale)
.ticks(5)
.tickSize(width/100 + ' em')
.tickFormat(d3.format('.0s'))
;
xAxisG.call(xAxis);
yAxisG.call(yAxis);
return({svgObj : svg, groupObj: group, topMarksObj: topMarks, connectingMarksObj: connectingMarks, bottomMarksObj: bottomMarks, annotationObj: annotation});
//svg.call(zoom);
}
var obj2001 = makeChart(data, 2001, 'translate(20, -50)');
var obj1990 = makeChart(data, 1995, 'translate(550, -40)');
///For zooming
function zoomed() {
svg.attr("transform", d3.event.transform);
//gX.call(xAxis.scale(d3.event.transform.rescaleX(x)));
//gY.call(yAxis.scale(d3.event.transform.rescaleY(y)));
}
//for zooming
function resetted() {
svg.transition()
.duration(750)
.call(zoom.transform, d3.zoomIdentity);
}
///For zooming
var zoom = d3.zoom()
.scaleExtent([1, 40])
.translateExtent([[-100, 0], [width + 9000, height]])
.on("zoom", zoomed);
exitFunct(obj2001);
exitFunct(obj1990);
}
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(array){return(render(array));})
</script>
</body>
https://d3js.org/d3.v4.min.js
https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.6.3/d3-tip.min.js
https://cdnjs.cloudflare.com/ajax/libs/d3-legend/1.1.0/d3-legend.js