D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
RobertDelgado
Full window
Github gist
Project Prototype round 3
Built with
blockbuilder.org
<!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 {} .stem1990 {} .stem1991 {} .stem1992 {} .stem1993 {} .stem1994 {} .stem1995 {} .stem1996 {} .stem1997 {} .stem1998 {} .stem1999 {} .stem2001 {} .stem2002 {} .stem2003 {} .stem2004 {} .stem2005 {} .stem2006 {} .stem2007 {} .stem2008 {} .stem2009 {} .stem2010 {} .stem2011 {} .stem2012 {} .stem2013 {} .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> var height = 500; var width = 960; var margin = {top: 40, 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.scaleSqrt().domain([0,d3.max(data, d => d.GHG_Cum) + 1000]) .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'}); 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]); 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); 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].merge(stemObjBottom[yr]); stemObjBottom[yr] = attributes(stemObjBottom[yr], {height:function(d){return(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"}); }; 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 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"}) var popObj = generalUpdate(outerGroup, {obj:"circle", cl:".popObj"}, fYearData); popObj = generalEnter(popObj, {obj:"circle", cl:".popObj"}) popObj = popObj.merge(popObj); popObj =attributes(popObj, {r:d => Math.sqrt(3*d.Population/(1000000)) , fill: "rgba(10,10,10,.1)" , cx: d=> xScale(d.Country)+xScale.bandwidth()/2 , cy: d => yScale(d.GHG_Cum - d.GHG + factor * d.GHG) , stroke: "black" , 'stroke-dasharray': '5,5'} ) popObj.on('mouseover', function(d){ d3.select(this).attr('fill', 'rgba(0,0,255,.2)'); }) .on('mouseout', function(d){ d3.select(this).attr('fill', 'rgba(10, 10, 10, .1)') }) ; } 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, 1993, 10))}) </script> </body>
https://d3js.org/d3.v4.min.js