function worldMap() {
var chartContainer = d3.select(".geo-chart-map").html("");
var margin = {top:0,left:0,right:0,bottom:0};
var w = chartContainer.node().clientWidth - margin.left - margin.right,
h = chartContainer.node().clientHeight;
// height needss to somehow be dynamic
var zoomScale = 2;
var svg = chartContainer
.append("svg")
.attr("width", w + margin.left + margin.right)
.attr("height", h + margin.top + margin.bottom);
var zoomIt = d3.zoom()
.scaleExtent([1,10])
// [[x0, y0], [x1, y1]]
.translateExtent([[0,0], [w, h+(h*.25)]])
.on("zoom", zoomed);
var view = svg
.append("g")
.attr("transform","translate("+ margin.left +"," + margin.top +")");
function zoomed() {
view.attr("transform", d3.event.transform);
}
d3.select("[data-ui=zoom-reset]")
.on("click", resetted);
d3.select("[data-ui=zoom-in]")
.on("click", zoomIn);
d3.select("[data-ui=zoom-out]")
.on("click", zoomOut);
function resetted() {
svg.transition()
.duration(750)
.call(zoomIt.transform, d3.zoomIdentity);
}
function zoomIn() {
svg.transition()
.duration(750)
.call(zoomIt.scaleBy, zoomScale*(zoomScale/2));
}
function zoomOut() {
svg.transition()
.duration(750)
.call(zoomIt.scaleBy, zoomScale/(zoomScale*2));
}
svg.call(zoomIt);
///////////////
//// initi ////
///////////////
d3.queue()
.defer(d3.json,"https://unpkg.com/world-atlas@1/world/110m.json")
// data goes here
// .defer(d3.csv, "common/data/prm-2018-bmi.csv")
.await(ready);
function ready(err, data) {
if (err) throw error;
/////////////////////////
//// Data manipulate ////
/////////////// /////////
// data manipulation and correlation here
////////////////////
//// Render Map ////
/////////////// ////
var world = topojson.feature(data, data.objects.countries);
var path = d3.geoPath()
.projection(d3.geoMercator()
.fitExtent([[0, 0], [w, h+(h*.25)]], world));
var country = view.selectAll(".country-path")
.data(world.features)
.enter()
.append("path")
.attr("class","country-path")
.style("cursor","pointer")
.attr("d", function(d){
return path(d);
});
// .style("fill", function(d) {return threshold(valByCountry[d.properties.UN]); });
};
}
// https://bl.ocks.org/mbostock/2206590
// zoom to bounding box https://bl.ocks.org/mbostock/4699541
// country shape joining and cuts
// https://stackoverflow.com/questions/19041457/how-can-i-remove-a-line-from-the-110m-topojson-world-map
// responsive map
// http://bl.ocks.org/jczaplew/4444770
// missing data
// sudan - BMI has 736 - the code should be 729
// country number 732 - Western Sahara
// -99 - cyprus - latvia? somalia region??
// 238 Falkland Islands (Malvinas)
// 260 French Southern Territories
// helpful links
// https://bl.ocks.org/mbostock/7ec977c95910dd026812
// -99 might mean disputed territory like Kosovo. this topojson has 3
// also, we need BMI to provide the UN numeric-3 country code: M49 Standard
// http://www.nationsonline.org/oneworld/countrycodes/countrycodes_g.htm
// Naming comventions between un and prm need to match - otherwise, we need BMI to provide he M49 standard number IDs
// https://stackoverflow.com/questions/18326689/javascript-textcontent-is-not-working-in-ie8-or-ie7
// http://nicolasgallagher.com/canvas-fix-svg-scaling-in-internet-explorer/
// https://github.com/d3/d3-selection/blob/master/README.md#selection_insert
// https://bl.ocks.org/mbostock/db6b4335bf1662b413e7968910104f0f
var prmChoroMap = {
init:function(){
var chartContainer = d3.select(".geo-chart-map").html("");
var margin = {top:0,left:0,right:0,bottom:0};
var w = chartContainer.node().clientWidth - margin.left - margin.right,
h = chartContainer.node().clientHeight;
var svg = chartContainer
.append("svg")
.attr("width", w + margin.left + margin.right)
.attr("height", h + margin.top + margin.bottom)
.append("g");
////////////////////////////////////////////////////// ZOOM
var zoomScale = 2;
var transitionSpeed = 900;
var zoom = d3.zoom()
.scaleExtent([1,10])
// [[x0, y0], [x1, y1]]
.translateExtent([[0,0], [w, h+(h*.25)]])
.on("zoom", zoomed);
var view = svg
.append("g");
function zoomed() {
view.attr("transform", d3.event.transform);
}
d3.select("[data-ui=zoom-reset]")
.on("click", resetted);
d3.select("[data-ui=zoom-in]")
.on("click", zoomIn);
d3.select("[data-ui=zoom-out]")
.on("click", zoomOut);
var initialTransform = d3.zoomIdentity
.translate(0,0)
.scale(1);
function resetted() {
svg.transition()
.duration(transitionSpeed)
.call(zoom.transform, initialTransform);
}
function zoomIn() {
svg.transition()
.duration(transitionSpeed)
.call(zoom.scaleBy, zoomScale*(zoomScale/2));
}
function zoomOut() {
svg.transition()
.duration(transitionSpeed)
.call(zoom.scaleBy, zoomScale/(zoomScale*2));
}
svg.call(zoom).on("wheel.zoom", null);
// ZOOM END
//// READY
d3.queue()
.defer(d3.json,"https://unpkg.com/world-atlas@1/world/50m.json")
.defer(d3.csv, "common/data/prm-2018-bmi.csv")
.await(ready);
function ready(err, data, prmdata) {
if (err) throw error;
//// Ready Variables
var toggleLinks = d3.selectAll(".dv-wmap-mtoggle-item a");
var mapTitle = d3.select(".dv-wmap-mtoggle-title");
var overlay = d3.select(".overlay");
var overlayDetail = overlay.select(".overlay-detail");
var overlayTitle = overlay.select(".overlay-detail-title");
var overlayClose = overlay.select(".overlay-close");
var overlayBlurb = overlay.select(".overlay-detail-blurb");
var overlayChartContainer = overlay.select(".overlay-chart-container");
var active = d3.select(null);
var newIdentity;
//// Data manipulate | build x-data reference methods
var countryByCode = {};
prmdata.forEach(function(d){
countryByCode[d["ISO Numeric Code"]] = d.Country;
});
var criByCode = {};
prmdata.forEach(function(d){
criByCode[d["ISO Numeric Code"]] = +d.CRI;
});
var opriByCode = {};
prmdata.forEach(function(d){
opriByCode[d["ISO Numeric Code"]] = +d.OPRI;
});
var ltpriByCode = {};
prmdata.forEach(function(d){
ltpriByCode[d["ISO Numeric Code"]] = +d.LTPRI;
});
var lteriByCode = {};
prmdata.forEach(function(d){
lteriByCode[d["ISO Numeric Code"]] = +d.LTERI;
});
var stpriByCode = {};
prmdata.forEach(function(d){
stpriByCode[d["ISO Numeric Code"]] = +d.STPRI;
});
var steriByCode = {};
prmdata.forEach(function(d){
steriByCode[d["ISO Numeric Code"]] = +d.STERI;
});
var blurbByCode = {};
prmdata.forEach(function(d){
blurbByCode[d["ISO Numeric Code"]] = d["Political Blurb"];
});
//// Render Map
var world = topojson.feature(data, data.objects.countries);
var path = d3.geoPath()
.projection(d3.geoMercator()
.rotate([-8,0])
// .fitExtent([[0, -h+(h*.75)], [w, h+(h*.5)]], world));
// .fitExtent([[0, 0], [w, h+(h*.25)]], world));
.fitExtent([[0, 0], [w, h]], world));
var fullData = world.features;
//// Manipulate topo data
fullData.forEach(function(d){
d.country = countryByCode[d.id];
d.steri = steriByCode[d.id];
d.lteri = lteriByCode[d.id];
d.stpri = stpriByCode[d.id];
d.ltpri = ltpriByCode[d.id];
d.opri = opriByCode[d.id];
d.cri = criByCode[d.id];
d.blurb = blurbByCode[d.id];
});
//// country click function
function clicked(d) {
//// zoom map
if (active.node() === this) return reset(d);
active.classed("active", false);
view.selectAll(".country-path").style("fill","#ffffff");
active = d3.select(this).classed("active", true);
active.style("fill",function(d){
if (d.cri == undefined) {
return "#d8d8d8";
} else {
return thresholdCri(d.cri);
}
});
var bounds = path.bounds(d),
dx = bounds[1][0] - bounds[0][0],
dy = bounds[1][1] - bounds[0][1],
x = (bounds[0][0] + bounds[1][0]) / 2,
y = (bounds[0][1] + bounds[1][1]) / 2,
scale = .9 / Math.max(dx / (w/3), dy / h),
translate = [w / 4 - scale * x, h / 3 - scale * y];
newIdentity = d3.zoomIdentity
.translate(w / 4 - scale * x, h / 3 - scale * y)
.scale(.9 / Math.max(dx / (w/3), dy / h));
svg.transition()
.duration(transitionSpeed)
.call(zoom.transform, newIdentity);
// zoom map end
overlay.classed("is-show", true);
overlayTitle.html(d.country + "<p class=\'sub-title\'>Risk Index Score</p>");
overlayBlurb.html(d.blurb);
overlayChartContainer.html("");
barChart(d);
function barChart(d){
//// manipuate data | create index only dataset
var barData = d3.entries(d).filter(function(d){
return d.key == "steri" ||
d.key == "cri" ||
d.key == "lteri" ||
d.key == "opri" ||
d.key == "ltpri" ||
d.key == "stpri";
;
});
//// manipuate data | Rename the labels
barData.forEach(function(d){
if (d.key == "steri") {
d.name = "Short Term Economic Risk";
}
if (d.key == "cri") {
d.name = "Country Risk";
}
if (d.key == "lteri") {
d.name = "Long Term Economic Risk";
}
if (d.key == "opri") {
d.name = "Operational Risk";
}
if (d.key == "ltpri") {
d.name = "Long Term Political Risk";
}
if (d.key == "stpri") {
d.name = "Short Term Political Risk";
}
});
var barMargin = {
top:40,
left:0,
right:0,
bottom:80
};
var barW = overlayChartContainer.node().clientWidth - barMargin.left - barMargin.right,
barH = 400 - barMargin.top - barMargin.bottom;
var barxscale = d3.scaleBand()
.rangeRound([0,barW])
.domain(barData.map(function(d){ return d.key;}))
.paddingInner(0.15);
var baryscale = d3.scaleLinear()
.domain([0, 100])
.range([barH,0]);
var barxaxis = d3.axisBottom(barxscale);
var barSvg = overlayChartContainer
.append("svg")
.attr("width", (barW + barMargin.left + barMargin.right))
.attr("height", (barH + barMargin.top + barMargin.bottom))
.append("g.bar-wrap")
.translate([barMargin.left,barMargin.top]);
barSvg.append("g.x-axis")
.call(barxaxis)
.attr("transform","translate(0," + barH + ")")
.selectAll("text")
.style("text-anchor","middle")
.classed("x-label",true)
.attr("dy", 0)
.attr("x", 0)
.attr("y", 10);
var gRect = barSvg.selectAll("g.g-rects")
.data(barData)
.enter()
.append("g.g-rects");
gRect
.append("rect.comp-rect")
.attr("x",function(d){
return barxscale(d.key);
})
.attr("y",function(d){
return baryscale(d.value) - 5;
})
.attr("width",barxscale.bandwidth())
.attr("height",function(d){
return barH - baryscale(d.value);
})
.style("fill", function(d){
return thresholdCri(d.value);
});
gRect
.append("text")
.attr("x", function(d) { return barxscale(d.key) + barxscale.bandwidth()/2; })
.attr("y", function(d) { return baryscale(d.value) - 15; })
.attr("dy", 2)
.attr("text-anchor","middle")
.text(function(d){ return d.value; });
}
// end barchart
}
// end clicked
//// reset function
function reset(d) {
active.classed("active", false);
active = d3.select(null);
overlayTitle.html("");
overlayBlurb.html("");
overlayChartContainer.html("");
overlay.classed("is-show", false);
view.selectAll(".country-path").style("fill", function(d){
if (d.cri == undefined) {
return "#d8d8d8";
} else {
return thresholdCri(d.cri);
}
});
resetted();
}
// end reset
// color
// threshold = domain needs one less value that range
var thresholdCri = d3.scaleThreshold()
.domain([50, 60, 70, 80, 100])
.range(['#ef4f46','#fcaf17','#ffcc7b','#bae1d3','#7ecab2','#ffffff']);
var thresholdOpri = d3.scaleThreshold()
.domain([50, 60, 70, 80, 100])
.range(['#004280','#0080b2','#00b0d3','#66d0e5','#9edcea','#ffffff']);
var thresholdLtpri = d3.scaleThreshold()
.domain([50, 60, 70, 80, 100])
.range(['#8d380a','#c55f24','#f58233','#f9b484','#fdd9bc','#ffffff']);
var thresholdLteri = d3.scaleThreshold()
.domain([50, 60, 70, 80, 100])
.range(['#00582d','#128c3f','#72bf44','#aad98f','#cbe4b7','#ffffff']);
var country = view.selectAll(".country-group")
.data(fullData)
.enter()
.append("g.country-group");
var countryPath = country
.append("path")
.attr("class","country-path")
.attr("d", function(d){
return path(d);
})
.on("click", clicked)
.style("fill", function(d) {
if (criByCode[d.id] == undefined) {
return "#d8d8d8";
} else {
return thresholdCri(d.cri);
}
});
// Events
country
.on("mouseenter", function(d){
d3.select('body').selectAppend('div.tooltip');
d3.select(this).call(d3.attachTooltip);
d3.select('.tooltip')
.html("<p class=\'tooltip-title\'>" + d.country +
"</p><p class=\'tooltip-info\'>Country Risk Index: <span>" + d.cri + "</span>" +
"</p><p class=\'tooltip-info\'>Political Risk Index: <span>" + d.ltpri + "</span>" +
"</p><p class=\'tooltip-info\'>Operational Risk Index: <span>" + d.opri + "</span>" +
"</p><p class=\'tooltip-info\'>Economic Risk Index: <span>" + d.lteri + "</span></p>");
});
overlayClose
.on("click", function(){
overlayTitle.html("");
overlayBlurb.html("");
overlayChartContainer.html("");
overlay.classed("is-show", false);
reset();
});
toggleLinks.on("click", function(){
var d3this = d3.select(this);
var dataVal = d3this.attr("data-map");
toggleLinks.classed("is-inactive", false);
d3this.classed("is-inactive", true);
mapTitle.text(d3this.text());
svg.selectAll(".country-path")
.transition().duration(transitionSpeed)
.style("fill", function(d) {
// if no data, color grey
if (criByCode[d.id] == undefined) {
return "#d8d8d8";
} else {
if (dataVal == "lteri") {
return thresholdLteri(d.lteri);
}
if (dataVal == "ltpri") {
return thresholdLtpri(d.ltpri);
}
if (dataVal == "opri") {
return thresholdOpri(d.opri);
}
if (dataVal == "cri") {
return thresholdCri(d.cri);
}
}
});
mxDropMenu.close(".dv-wmap-mtoggle-list", ".dv-wmap-mtoggle-select", ".geo-chart-map");
});
}; // end of ready
}
};
var mxDropMenu = {
open:function(elem, btn, map){
$(map).addClass("is-blur");
$(btn).addClass("is-active");
$(elem).addClass('is-drop');
},
close:function(elem, btn, map){
$(map).removeClass("is-blur");
$(btn).removeClass("is-active");
$(elem).removeClass('is-drop');
},
init: function(settings){
$(settings.button).on('click', function(){
if ($(settings.list).hasClass('is-drop')) {
// if open
mxDropMenu.close(settings.list, settings.button, settings.map);
} else {
// if closed
mxDropMenu.open(settings.list, settings.button, settings.map);
}
});
}
};
var settings = {
list: ".dv-wmap-mtoggle-list",
button: ".dv-wmap-mtoggle-select",
map:".geo-chart-map"
}
mxDropMenu.init(settings);