Built with blockbuilder.org
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://cdn.jsdelivr.net/lodash/4.16.2/lodash.min.js"></script>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-geo-projection.v1.min.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<script src="https://d3js.org/d3-queue.v3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-legend/2.9.0/d3-legend.js"></script>
<script src="https://d3js.org/topojson.v1.min.js"></script>
<style>
body {
/* margin:0;
position:fixed;
top:0;
right:0;
bottom:0;
left:0; */
}
svg {
background: white;
}
.geo-units {
fill: none;
}
path {
stroke: #fff;
stroke-width: 0.5px;
stroke-linejoin: round;
}
.caption {
font-weight: bold;
fill: #fff
}
.key text {
fill: black;
font-family: monospace;
}
.key path {
display: none;
}
</style>
</head>
<body>
<script>
// Feel free to change or delete any of the code you see in this editor!
var g3 = {
opts: {},
dimensions: {
width: 0,
height: 0
},
data: [],
bindTo: "body",
formatAbbreviation: function(x) {
var formatNumber = d3.format(".0f"),
formatBillion = function(x) { return "$" + formatNumber(x / 1e9) + "B"; },
formatMillion = function(x) { return "$" + formatNumber(x / 1e6) + "M"; },
formatThousand = function(x) { return "$" + formatNumber(x / 1e3) + "k"; };
var v = Math.abs(x);
return (v >= .9995e9 ? formatBillion
: v >= .9995e6 ? formatMillion
: formatThousand)(x);
}
};
g3.map = function(opts) {
var self = this;
var resizeMap = _.debounce(function() { initialize(opts); }, 150);
d3.select(window).on("resize.map", resizeMap);
initialize(opts);
function initialize(opts) {
self.opts = opts;
self.data = opts.data;
self.bindTo = opts.bindTo || self.bindTo;
self.d3DOM = d3.select(self.bindTo);
self.dimensions.width = +self.d3DOM.style("width").slice(0, -2);
self.dimensions.height = +self.d3DOM.style("height").slice(0, -2);
}
}
var stateById = d3.map(),
amtsByState = d3.map();
var colors = ["rgb(237,248,251)", "rgb(191,211,230)", "rgb(158,188,218)", "rgb(140,150,198)", "rgb(140,107,177)", "rgb(136,65,157)", "rgb(110,1,107)"];
var quantile = null;
var x = null;
var xAxis = null;
var colorLegend = null;
var q = d3.queue()
.defer(d3.csv,"contractor_state.csv",function(d) {
var stateAmts = _.range(2000,2016).map(function(year) {
return d[year].replace(/[$,]/g,"");
})
amtsByState.set(d.code, stateAmts);
return d;
})
.defer(d3.csv,"contractor_country.csv")
.await(mungeData)
function mungeData(err, states, countries) {
if (err) throw err;
var allAmtsArr = _.flattenDeep(amtsByState.values());
quantile = d3.scaleQuantile()
.range(colors)
.domain(allAmtsArr)
x = d3.scaleLinear()
.domain([0, d3.max(allAmtsArr)])
.range([0, 400]);
xAxis = d3.axisBottom()
.scale(x)
.tickSize(13)
.tickValues(quantile.domain())
colorLegend = d3.legendColor()
.labelFormat(g3.formatAbbreviation)
.labelDelimiter("")
.shapeWidth(40)
.orient('horizontal')
.scale(quantile);
var ocDataObj = {
states: states
// countries: countries
}
var ocKeysArr = _.keys(ocDataObj),
discoverDataJSON = null,
yearsArr = _.range(2000,2016);
function summaryStats(key, year) {
// ret object of objects
var amtArr = [],
currAmtKeyStr = year;
var amtsByAreaArr = ocDataObj[key].map(function(row, idx) {
var amtByYear = {
code: row.code,
name: row.name,
amount: row[currAmtKeyStr],
amountFloat: +row[currAmtKeyStr].replace(/[$,]/g,""),
}
return amtByYear;
})
var amtsDescArr = _.sortBy(amtsByAreaArr, function(amt) { return -amt.amountFloat});
amtArr = amtsDescArr.filter(function(currAmt, idx) {
return (currAmt.name === "null")? false : true;
}).map(function(currAmt, idx) {
return {
key: currAmt.code,
value: currAmt.amount
};
});
var retArr = [{ key: "highest ammounts", values: amtArr }];
return retArr;
}
discoverDataJSON = ocKeysArr.map(function(ocKey,ocIdx) {
return {
key: ocKey,
values: yearsArr.map(function(year,yearIdx) {
return {
key: year,
values: summaryStats(ocKey, year)
}
})
};
});
var q2 = d3.queue()
// .defer(d3.json,"https://gist.githubusercontent.com/mbostock/4090846/raw/d534aba169207548a8a3d670c9c2cc719ff05c47/world-50m.json")
.defer(d3.json,"https://gist.githubusercontent.com/mbostock/4090846/raw/d534aba169207548a8a3d670c9c2cc719ff05c47/us.json")
.defer(d3.csv,"state_table.csv",function(d){stateById.set(d.fips_state,d.abbreviation)})
.await(function(error, us, state_table) {
if (err) throw err;
var geoData = {
// world:world,
us:us
};
initD3(discoverDataJSON,geoData);
});
}
function initD3(dataObj,geoData) {
var ratio = 1.6;
var width = d3.select('body').node().getBoundingClientRect().width,
height = width / ratio,
us = geoData.us;
// world = geoData.world;
// geo setup
var usProjection = d3.geoAlbersUsa()
.scale(1280)
.translate([width / 2, height / 2]);
// var worldProjection = d3.geoKavrayskiy7()
// .scale(170)
// .translate([width / 2, height / 2]);
var usPath = d3.geoPath()
.projection(usProjection);
// var worldPath = d3.geoPath()
// .projection(worldProjection);
// two divs: states, countries
var geoDivs = d3.select('body')
.selectAll('.geo-unit')
.data(dataObj)
.enter().append('div')
.attr('class', 'geo-unit')
.attr('id', function(d) { return d.key });
// 32 svgs: 16 years for states, 16 for countries
var svgs = geoDivs.selectAll('svg')
.data(function(d) { return d.values; })
.enter().append('svg')
.style("width", width)
.style("height", height)
var gs = svgs.append("g")
.attr("class", "units")
.attr("id", function(d) { return "fy" + d.key;})
var keys = svgs.append("g")
.attr("class", "key")
.attr("transform", "translate(" + width/1.5 + "," + height/10 + ")")
.each(function(d, i) {
d3.select(this).call(colorLegend);
});
keys.append('text')
.text(function() {
return d3.select(this.parentNode.previousSibling).attr("id").replace("fy","")
})
.style('font-size', '2.5em')
.attr('y', -10)
keys.select('.legendCells')
.selectAll('.label')
.text(function() { return d3.select(this).text().split(" ")[0] })
var paths = gs.selectAll("path")
.data(function(d) {
var currGeoData = null;
var geoUnitId = d3.select(this.parentNode.parentNode)
.attr("id");
// if (geoUnitId === "states") {
// currGeoData = topojson.feature(us, us.objects.states).features
// } else {
// currGeoData = topojson.feature(world, world.objects.countries).features
// }
currGeoData = topojson.feature(us, us.objects.states).features
return currGeoData;
})
.enter().append("path")
paths.attr("fill", function(d) {
var geoUnitId = d3.select(this.parentNode.parentNode.parentNode)
.attr("id");
var geoUnitIdx = _.findIndex(dataObj, ['key',geoUnitId]); // findIndex using geoUnitId
var currGeoUnitValues = dataObj[geoUnitIdx].values;
var yearId = d3.select(this.parentNode)
.attr("id").replace("fy","");
var yearIdx = _.findIndex(currGeoUnitValues, ['key', +yearId]); // findIndex using yearId
var currYearCollection = currGeoUnitValues[yearIdx].values[0].values;
var currUnit = stateById.get(d.id);
var unitIdx = _.findIndex(currYearCollection, ['key', currUnit])// find on indexed dataObj & parse
if (unitIdx > -1) {
var unitAmt = +currYearCollection[unitIdx].value.replace(/[$,]/g,"");
return quantile(unitAmt);
}
})
.attr("d", function(d) {
var geoUnitId = d3.select(this.parentNode.parentNode.parentNode)
.attr("id");
// return (geoUnitId === "states")? usPath(d) : worldPath(d);
return usPath(d)
})
.attr("class", function(d) { return stateById.get(d.id) });
}
</script>
</body>
Modified http://d3js.org/topojson.v1.min.js to a secure url
https://cdn.jsdelivr.net/lodash/4.16.2/lodash.min.js
https://d3js.org/d3.v4.min.js
https://d3js.org/d3-geo-projection.v1.min.js
https://d3js.org/d3-scale-chromatic.v1.min.js
https://d3js.org/d3-queue.v3.min.js
https://cdnjs.cloudflare.com/ajax/libs/d3-legend/2.9.0/d3-legend.js
https://d3js.org/topojson.v1.min.js