Skip to content

Instantly share code, notes, and snippets.

@piwodlaiwo
Last active January 25, 2018 21:58
Show Gist options
  • Save piwodlaiwo/a86e110a32e73c997011ea8b8ce8f989 to your computer and use it in GitHub Desktop.
Save piwodlaiwo/a86e110a32e73c997011ea8b8ce8f989 to your computer and use it in GitHub Desktop.
Country Labels based on Area, Zoom, and Centroid
license: mit
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.js"></script>
<!--<script src="https://d3js.org/topojson.v2.min.js"></script>-->
<script src="https://unpkg.com/topojson-client@3"></script>
<script src="https://d3js.org/queue.v1.min.js"></script>
<style>
body { margin:10px;position:fixed;top:0;right:0;bottom:0;left:0; }
#map { border:1px solid #000; background:#C6ECFF; }
.country {fill:#FDFBEA;stroke: #000;}
.graticule {
fill: none;
stroke: #bbb;
stroke-width: .5px;
stroke-opacity: .5;
}
svg text {display:none;}
.zoom1 text.zoom1 {display:block;font-size:14px}
.zoom1 text.zoom2 {display:block;font-size:10px}
/*
text {display:block;}
text.init {display:block;}
.zoom1 text.rest,.zoom2 text.rest {display:none;}
.zoom1 text {font-size:14px;}
.zoom2 text {font-size:12px;}
.zoom3 text {font-size:10px;}
.zoom4 text {font-size:8px;}
.zoom5 text {font-size:6px;}
.zoom6 text {font-size:4px;}
.zoom7 text,.zoom8 text,.zoom9 text {font-size:2px;}
*/
</style>
</head>
<body>
<div id="map"></div>
<script>
const map = d3.select("#map");
const width = map.node().getBoundingClientRect().width;
const height = width / 2;
const projection = d3.geoMercator();
const path = d3.geoPath().projection(projection);
const zoom = d3.zoom()
.scaleExtent([1, 40])
.translateExtent([[0,0], [width, height]])
.extent([[0, 0], [width, height]])
.on("zoom", zoomed);
const svg = map.append("svg")
.attr("width", width)
.attr("height", height)
.attr("class", "zoom1")
.call(zoom);
const g = svg.append("g");
queue()
.defer(d3.json, "https://cdn.rawgit.com/mbostock/4090846/raw/d534aba169207548a8a3d670c9c2cc719ff05c47/world-50m.json")
.defer(d3.tsv, "https://cdn.rawgit.com/mbostock/4090846/raw/d534aba169207548a8a3d670c9c2cc719ff05c47/world-country-names.tsv")
.await(ready);
function ready(error, world, names) {
if (error) throw error;
var countries = topojson.feature(world, world.objects.countries).features;
//map country names to IDs used on map
var names_arr=[];
names.forEach(function(i){
names_arr[i.id]=i.name;
});
// Compute each country’s centroid and its area
countries.forEach(function(feature) {
feature.properties.area = d3.geoArea(feature);
//feature.properties.center = d3.geoCentroid(feature);
feature.properties.center = projection(d3.geoCentroid(feature));
feature.properties.name = names_arr[feature.id];
});
//console.log(countries[0]);
// Sort the countries by area
countries.sort(function(countryA, countryB) {
return countryB.properties.area - countryA.properties.area;
});
var c_min = countries[0].properties.area.toFixed(8);
var c_max = countries[countries.length-1].properties.area.toFixed(8);
console.log( c_min );
console.log( c_max );
//https://github.com/d3/d3-scale
//d3.scaleSqrt(), d3.scaleLog()
//this isnt great as .4 to .1 is zoom1 to zoom6!
var textrange = d3.scaleLinear().domain([c_min,c_max]).range([1, 9]);
console.log( textrange(0.11519723) );
//console.log( textrange(0.00001112) );
//https://github.com/d3/d3-array/blob/master/README.md#histogram_thresholds
//var histogram = d3.histogram().domain([0,100]).thresholds(5);
//console.log(histogram([1,2,3,11,21,55,77]));
//countries.forEach(function(c){
//console.log(c.properties.name+' area is '+c.properties.area.toFixed(8))
//});
g.selectAll("path")
.data(countries)
.enter()
.append("path")
.attr("id", function (d){ return 'id_'+d.id; })
.attr("class", "country")
.attr("d", path);
g.selectAll("text").data(countries)
.enter().append("text")
.attr("x", function (d){ return d.properties.center[0]; })
.attr("y", function (d){ return d.properties.center[1]; })
.attr("class", function (d,i){
return "zoom"+parseInt(textrange(d.properties.area.toFixed(8)))
//could use d to base it of area but its sorted so using i
//if(i<10){
// return "init";
//} else {
// return "rest";
//}
})
.attr("text-anchor", "middle")
.text(function(d) {
return d.properties.name;
})
//.style('fill', 'red');
//.style('font-size', function (d){
// return textrange(d.properties.area.toFixed(8))
//});
//you dont need to preslice!
/*
var big = countries.slice(0,100);
var small = countries.slice(100,240);
g.selectAll("text").data(big)
.enter().append("text")
.attr("x", function (d){ return d.properties.center[0]; })
.attr("y", function (d){ return d.properties.center[1]; })
.attr("class", "big")
.attr("text-anchor", "middle")
.text(function(d) {
//return d.properties.name;
//return d.properties.area;
});
g.selectAll("text").data(small)
.enter().append("text")
.attr("x", function (d){ return d.properties.center[0]; })
.attr("y", function (d){ return d.properties.center[1]; })
.attr("class", "small")
.attr("text-anchor", "middle")
.text(function(d) {
//return d.properties.name;
});
*/
//Did not need polylabel.js for labels
//https://bl.ocks.org/Fil/da021023d58b8ddefd165c65e37f796b
//http://blockbuilder.org/pnavarrc/75ec1502f51f86c2f43e
//http://bl.ocks.org/hugolpz/42955069888057aff8c2
//http://blockbuilder.org/d3noob/401237468c9e38cea8c7
//dont put text inside of path but maybe group them in their own g
/*
g.selectAll("path")
.data(countries)
.enter()
.append("path")
.attr("d", path)
.append("text")
.attr("x", function (d){ return d.properties.center[0]; })
.attr("y", function (d){ return d.properties.center[1]; })
.attr("class", "name")
.text(function(d) {
return d.properties.name;
});
*/
/*
g.selectAll("path")
.data(countries)
.enter()
.append("path")
.attr("d", path);
//g.selectAll("text").data(centroids)
g.selectAll("text").data(countries)
.enter().append("text")
//.attr("x", function (d){ return d[0]; })
//.attr("y", function (d){ return d[1]; })
.attr("x", function (d){ return d.properties.center[0]; })
.attr("y", function (d){ return d.properties.center[1]; })
.attr("class", "name")
//.attr("dy", 5)
//.style("fill", "black")
.attr("text-anchor", "middle")
.text(function(d) {
//console.log(arr[countries[i].id]);
//return arr[countries[i].id];
return d.properties.name;
});
*/
};
function zoomed(){
g.attr("transform", d3.event.transform);
var s = d3.event.transform.k;
d3.selectAll(".country").style("stroke-width", 1 / s);
//better to adjust text zoom with CSS
//d3.selectAll("text").style("font-size", 14-parseInt(s)+"px");
console.log( "zoom"+parseInt(s) );
svg.attr("class","zoom"+parseInt(s));
}
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment