|
<!DOCTYPE html> |
|
<meta charset="utf-8"> |
|
<style> |
|
body {} |
|
|
|
svg { |
|
font: 14px serif; |
|
} |
|
|
|
.caption { |
|
font-weight: bold; |
|
} |
|
|
|
.key path { |
|
display: none; |
|
} |
|
|
|
.key line { |
|
stroke: #000; |
|
shape-rendering: crispEdges; |
|
} |
|
|
|
.stroke { |
|
fill: none; |
|
stroke: #000; |
|
stroke-width: 3px; |
|
} |
|
|
|
.fill { |
|
fill: #fff; |
|
} |
|
|
|
.graticule { |
|
fill: none; |
|
stroke: #ddd; |
|
stroke-width: .5px; |
|
stroke-opacity: .5; |
|
} |
|
|
|
.countries{ |
|
fill: #ddd; |
|
} |
|
|
|
.boundary { |
|
fill: none; |
|
stroke: #ccc; |
|
stroke-width: .5px; |
|
} |
|
|
|
.label { |
|
fill: #777; |
|
} |
|
|
|
.overlay { |
|
fill: none; |
|
pointer-events: all; |
|
cursor: ew-resize; |
|
} |
|
|
|
aside { |
|
font-size: small; |
|
right: 0; |
|
position: absolute; |
|
width: 180px; |
|
} |
|
|
|
</style> |
|
<body> |
|
<script src="http://d3js.org/queue.v1.min.js"></script> |
|
<script src="http://d3js.org/d3.v3.min.js"></script> |
|
<script src="http://d3js.org/topojson.v1.min.js"></script> |
|
<script src="http://d3js.org/d3.geo.projection.v0.min.js"></script> |
|
|
|
<div id="map"></div> |
|
<div> |
|
</div> |
|
<script> |
|
var width = 960, |
|
height = 600; |
|
|
|
var color = d3.scale.threshold() |
|
.domain([0, 20, 50, 90]) |
|
.range(["#ffffcc","#fcbba1","#fc9272","#ef3b2c","#a50f15"]); |
|
|
|
var x = d3.scale.linear() |
|
.domain([0, 100]) |
|
.range([0, 150]); |
|
|
|
var xAxis = d3.svg.axis() |
|
.scale(x) |
|
.orient("bottom") |
|
.tickSize(13) |
|
.tickValues(color.domain()); |
|
|
|
// Accessors for dimensions of the data |
|
function key(d) { return d.id; } |
|
var usageByCountryCode = d3.map(); |
|
var minYear = 2018; |
|
var maxYear = 2018; |
|
|
|
var projection = d3.geo.kavrayskiy7() |
|
.scale(150) |
|
.translate([width / 2 - 40, height / 2 + 30]) |
|
.rotate([-10,0]) |
|
.precision(.1); |
|
|
|
var path = d3.geo.path() |
|
.projection(projection); |
|
|
|
var graticule = d3.geo.graticule(); |
|
|
|
var svg = d3.select("#map").append("svg") |
|
.attr("width", width) |
|
.attr("height", height); |
|
|
|
var label = svg.append("text") |
|
|
|
// Creates the scale |
|
var g = svg.append("g") |
|
.attr("class", "key") |
|
.attr("transform", "translate(15,50)"); |
|
|
|
g.selectAll("rect") |
|
.data(color.range().map(function(d, i) { |
|
return { |
|
x0: i ? x(color.domain()[i - 1]) : x.range()[0], |
|
x1: isNaN(i) < color.domain().length ? x(color.domain()[i]) : x.range()[1], |
|
z: d |
|
}; |
|
})) |
|
.enter().append("rect") |
|
.attr("height", 12) |
|
.attr("x", function(d) { return d.x0; }) |
|
.attr("width", function(d) { return d.x1 - d.x0; }) |
|
.style("fill", function(d) { return d.z; }); |
|
|
|
g.call(xAxis).append("text") |
|
.attr("class", "caption") |
|
.attr("y", -6) |
|
.text("Foreign currency debt (% of GDP)"); |
|
|
|
var noD = g.append("rect") |
|
.attr("height", 12) |
|
.attr("x", 0) |
|
.attr("y", 40) |
|
.attr("width", 15) |
|
.style("fill", "gray"); |
|
|
|
g.append("text") |
|
.attr("class", "caption") |
|
.attr("x", 20) |
|
.attr("y", 50) |
|
.text("no data"); |
|
|
|
svg.append("defs").append("path") |
|
.datum({type: "Sphere"}) |
|
.attr("id", "sphere") |
|
.attr("d", path); |
|
|
|
svg.append("use") |
|
.attr("class", "stroke") |
|
.attr("xlink:href", "#sphere"); |
|
|
|
svg.append("use") |
|
.attr("class", "fill") |
|
.attr("xlink:href", "#sphere"); |
|
|
|
svg.append("path") |
|
.datum(graticule) |
|
.attr("class", "graticule") |
|
.attr("d", path); |
|
|
|
queue() |
|
.defer(d3.json, "world-50m.json") |
|
.defer(d3.csv, "sovdebt.csv", function(d) { usageByCountryCode.set(d["Country Code"], d); }) |
|
.await(ready); |
|
|
|
function ready(error, world) { |
|
var countries = topojson.feature(world, world.objects.countries).features, |
|
neighbors = topojson.neighbors(world.objects.countries.geometries); |
|
|
|
var state = svg.insert("g", ".graticule") |
|
.attr("class", "countries"); |
|
state.selectAll(".country") |
|
.data(countries) |
|
.enter() |
|
.append("path") |
|
.attr("class", "country") |
|
.attr("d", path) |
|
.attr("fill", function(d) { |
|
var code = usageByCountryCode.get(d.id); |
|
if (typeof code == "undefined") console.log("name=" + d.properties.name + ", code=" + d.id); |
|
return (typeof code != "undefined") ? color(code[minYear]) : "#ddd"; |
|
}) |
|
.append("title") |
|
.text(function(d) { |
|
var code = usageByCountryCode.get(d.id); |
|
; |
|
|
|
return d.properties.name + ((typeof code != "undefined") ? (isNaN(code[minYear]) ? "" : (": " + code[minYear] +"% of GDP")) : ""); }) |
|
|
|
svg.insert("path", ".graticule") |
|
.datum(topojson.mesh(world, world.objects.countries, function(a, b) { return a !== b; })) |
|
.attr("class", "boundary") |
|
.attr("d", path); |
|
}; |
|
d3.select(self.frameElement).style("height", height + "px"); |
|
|
|
</script> |