(This chart is a part of the d3-charts
collection available here.)
This is the multicolour version of the World Map chart. For more, visit its page.
The chart shows the number of patent filing logarithmically in the respective countries using data from ok-dk.
The following countries have returned an error according to the log, as the data has not been fine-combed and sanitized:
"Andorra", "Antigua and Barbuda", "Anguilla", "Netherlands Antilles", "Aruba", "Barbados", "Bahrain", "Bermuda", "Cook Islands", "Dominica", "Falkland Islands (Malvinas)", "Faroe Islands", "Grenada", "Gibraltar", "Hong Kong", "Iran, Islamic Republic of", "Saint Kitts and Nevis", "Korea, Democratic People's Republic of", "Korea, Republic of", "Cayman Islands", "Saint Lucia", "Liechtenstein", "Monaco", "Moldova, Republic of", "Marshall Islands", "Macao", "Malta", "Mauritius", "Seychelles", "Singapore", "San Marino", "Turks and Caicos Islands", "Tokelau", "Taiwan, Province of China", "Saint Vincent and The Grenadines", "Venezuela, Bolivarian Republic of", "Virgin Islands British", "Virgin Islands US", "Viet Nam", "Samoa"
.
xxxxxxxxxx
<!--
- Scale SVG dynamically/responsively
- d3.tip
- Convert geojson to topojson: https://github.com/mbostock/world-atlas
ISSUE: With D3 book's shape file, Alabama disappears
ISSUE: With official shape file, Minnesota disappears
-->
<html lang="en">
<head>
<meta charset="utf-8">
<style>
svg {
margin-left: auto; margin-right: auto;
display: block;
}
line,
rect {
shape-rendering: crispEdges;
}
.states {
fill: none; /** Hides TopoJSON artifacts */
stroke: #000;
}
.counties {}
path.country,
path.state {
stroke-width: .5;
stroke: #FFF;
}
path.country:hover,
path.state:hover {
fill: pink !important;
}
/** State chart threshold BEGIN */
text {
font: 10px sans-serif;
}
.caption {
font-weight: bold;
}
.key path {
display: none;
}
.key line {
stroke: #000;
/** shape-rendering: crispEdges; */
}
/** State chart threshold END */
/** Bar chart BEGIN */
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path {
display: none;
}
rect.bar:hover {
fill: orange !important;
}
/** Bar chart END */
.divider {
stroke: #FFF;
opacity: 0.7;
}
/** Grid lines BEGIN */
/** https://www.d3noob.org/2013/01/adding-grid-lines-to-d3js-graph.html */
.grid .tick {
stroke: lightgrey;
opacity: 0.7;
}
.grid path {
stroke-width: 0;
}
/** Grid lines END */
</style>
<script src="d3.min.js?v=3.2.8"
type="text/javascript" charset="utf-8"></script>
<script src="d3.geo.projection.v0.min.js"
type="text/javascript" charset="utf-8"></script>
<!--
<script src="topojson.v1.min.js"
type="text/javascript" charset="utf-8"></script>
-->
</head>
<body>
<script type="text/javascript" charset="utf-8">
var width = 800,
height = 520,
padding = 30;
// Local settings
var dataset = "data.csv",
countryValue = "Country Name",
colors = ["#d7191c", "#2b83ba"];
// Settings---only for multicolour chart
var multiColor = true,
dataValue = "2013",
domain = [0, 14877], // []
useLogScale = true;
// Threshold settings---also only for multicolour chart
if (multiColor === true) {
var thresholdTitle = "No. of patent filings",
thresholdValuePrefix = "", // "$", "£"
thresholdValueSuffix = "", // "%", "Patents"
thresholdProportional = true,
formatWithZeroes = d3.format(","),
trimZeroes = true,
formatValue = function(d) {
var index = trimZeroes === true ? d3.formatPrefix(d3.max(domain)) : formatWithZeroes;
return trimZeroes === true ? index.scale(d) + index.symbol : index(d);
};
}
var showLegend = multiColor,
spacing = showLegend === true ? 30 : 0,
margin = {
top: spacing,
bottom: 0,
left: spacing,
right: spacing
};
margin.hor = margin.left + margin.right;
margin.ver = margin.top + margin.bottom;
var color = d3.scale.linear()
.range(colors)
.clamp(useLogScale)
.interpolate(d3.interpolateHcl);
var projection = d3.geo.kavrayskiy7()
.translate([width/2, height/2])
.scale(150); // Revise so it isn't a magic number
var path = d3.geo.path()
.projection(projection);
var svg = d3.select("body")
.append("svg")
.attr({
"width": width,
"height": height
});
// Load the data values
d3.csv(dataset, function(error, data) {
var countryList = data.map(function(d) { return d[countryValue]; }),
errorList = {};
data.map(function(d) { errorList[d[countryValue]] = d[dataValue] ? d[dataValue] : ""; });
if (multiColor === true && useLogScale === true) {
newDomain = domain.map(function(el) { return el === 0 ? 0 : Math.log(el); });
color.domain(newDomain); // Redundant to use newDomain?
} else {
color.domain(domain);
}
// Geodata loaded into the csv scope
d3.json("ne_110m_admin_0_countries_lakes.geojson", function(json) {
var dataLength = data.length,
jsonLength = json.features.length;
// Data (values) forloop
for (var i = 0; i < dataLength; i++) {
var countryName = data[i][countryValue],
countryData = useLogScale !== true ? data[i][dataValue] : Math.log(data[i][dataValue]);
// JSON (geodata) forloop
for (var j = 0; j < jsonLength; j++) {
if (countryName === json.features[j].properties.name_long) {
json.features[j].properties.value = multiColor === true ? countryData : true;
delete errorList[countryName];
break;
}
}
}
svg.selectAll("path")
.data(json.features)
.enter()
.append("path")
.attr({
"d": path,
"class": "country",
"transform": "translate(" + 0 + "," + margin.top + ")"
})
.style("fill", function(d) {
if (multiColor === true) {
return d.properties.value ? color(d.properties.value) : "#DDD";
} else {
return d.properties.value ? color.range()[1] : "#DDD";
}
});
// Error log
errorList = Object.keys(errorList);
if (errorList.length !== 0) {
console.log("An error occured trying to plot the following countries:");
console.log(errorList);
}
});
if (showLegend === true) {
var threshold = d3.scale.threshold()
.domain(color.domain())
.range(color.range());
var keyX = d3.scale.linear()
.domain(d3.extent(threshold.domain()))
.range([0, (width - margin.hor)/2]); // total key width
var keyXAxis = d3.svg.axis()
.scale(keyX)
.orient("bottom")
.tickSize(13)
.tickValues(function(d, i) {
return thresholdProportional === true ? threshold.domain() : "TODO";
})
.tickFormat(function(d, i) {
return domain[i] ? formatValue(domain[i]) : thresholdValuePrefix + domain[i] + thresholdValueSuffix;
});
var g = svg.append("g")
.attr({
"class": "key",
"transform": "translate(" + margin.left + "," + margin.top + ")"
});
// Threshold bars
g.selectAll("rect")
.data(threshold.range().map(function(d, i) {
if (thresholdProportional === true) {
var startingPoint = i ? keyX(threshold.domain()[i-1]) : keyX.range()[0];
} else {
var startingPoint = i ? keyX.range()[1] / domain.length * i : keyX.range()[0];
}
return {
x0: startingPoint,
// Unused if thresholdProportional === true
x1: i < threshold.domain().length ? keyX(threshold.domain()[i]) : keyX.range()[1],
z: d
};
}))
.enter()
.append("rect")
.attr({
"height": 8,
"x": function(d) { return d.x0; },
"width": thresholdProportional === true ? function(d) { return d.x1 - d.x0; } : keyX.range()[1] / domain.length
})
.style("fill", function(d) { return d.z; });
// Threshold title
if (thresholdProportional === true) {
g.call(keyXAxis)
.append("text")
.attr({
"class": "caption",
"y": -6
})
.text(thresholdTitle);
}
}
});
</script>
</body>
</html>