Skip to content

Instantly share code, notes, and snippets.

@oroojo
Last active September 28, 2017 10:10
d3 v4 Map with centered labels
license: mit
[{"country":"ppp_1_Bomi_63","name":"Bomi","value":6.3},{"country":"ppp_2_Bong_63","name":"Bong","value":6.3},{"country":"ppp_3_Gbarpolu_58","name":"Gbarpolu","value":5.8},{"country":"ppp_4_Grand Cape Mount_48","name":"Grand Cape Mount","value":4.8},{"country":"ppp_5_Grand Bassa_51","name":"Grand Bassa","value":5.1},{"country":"ppp_6_Grand Gedeh_54","name":"Grand Gedeh","value":5.4},{"country":"ppp_7_Grand Kru_61","name":"Grand Kru","value":6.1},{"country":"ppp_8_Lofa_49","name":"Lofa","value":4.9},{"country":"ppp_9_Margibi_51","name":"Margibi","value":5.1},{"country":"ppp_10_Maryland_68","name":"Maryland","value":6.8},{"country":"ppp_11_Montserrado_52","name":"Montserrado","value":5.2},{"country":"ppp_12_Nimba_41","name":"Nimba","value":4.1},{"country":"ppp_13_River Cess_39","name":"River Cess","value":3.9},{"country":"ppp_14_River Gee_44","name":"River Gee","value":4.4},{"country":"ppp_15_Sinoe_42","name":"Sinoe","value":4.2},{"country":"x1","name":"x1","value":0},{"country":"x","name":"x","value":10}]
<html>
<head>
<style>
body {
margin: 0;
font-family: "Helvetica Neue", sans-serif;
}
.subunit {
fill: #ddd;
stroke: #fff;
stroke-width: 1px;
}
.subunit-boundary {
fill: none;
stroke: #3a403d;
}
.place-label {
font-size: .7em;
text-shadow: 0px 0px 2px #fff;
}
.subunit-label {
fill: #666;
font-size: 15px;
font-weight: 700;
text-anchor: middle;
background:white;
border-radius:3px;
}
#legend {
position:absolute;
top:0;
right:0px
}
</style>
</head>
<body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="//d3js.org/queue.v1.min.js"></script>
<script src="http://d3-legend.susielu.com/d3-legend.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.20/topojson.min.js"></script>
<div id="map-viz"> </div>
<script>
var color = d3.scaleThreshold()
.domain([1, 2, 3, 4, 5])
.range(["#f2f0f7", "#dadaeb", "#bcbddc", "#9e9ac8", "#756bb1", "#54278f"]);
var width = window.innerWidth, height = window.innerHeight;
var projection = d3.geoMercator();
var path = d3.geoPath()
.projection(projection)
.pointRadius(2);
var svg = d3.select("#map-viz").append("svg")
.attr("width", width)
.attr("height", height);
var g = svg.append("g");
queue()
.defer(d3.json, "liberia.json")
.defer(d3.json, "data.json")
.await(ready);
function ready(error, topojson, scores) {
if (error) throw error;
var boundary = centerZoom(topojson);
drawSubUnits(topojson, scores);
}
function centerZoom(data){
var o = topojson.mesh(data, data.objects.collection, function(a, b) { return a === b; });
projection
.scale(1)
.translate([0, 0]);
var b = path.bounds(o),
s = 1 / Math.max((b[1][0] - b[0][0]) / width, (b[1][1] - b[0][1]) / height),
t = [(width - s * (b[1][0] + b[0][0])) / 2, (height - s * (b[1][1] + b[0][1])) / 2];
projection
.scale(s)
.translate(t);
return o;
}
function drawOuterBoundary(data, boundary){
g.append("path")
.datum(boundary)
.attr("d", path)
.attr("class", "subunit-boundary");
}
function drawPlaces(data){
g.append("path")
.datum(topojson.feature(data, data.objects.places))
.attr("d", path)
.attr("class", "place");
g.selectAll(".place-label")
.data(topojson.feature(data, data.objects.places).features)
.enter().append("text")
.attr("class", "place-label")
.attr("transform", function(d) { return "translate(" + projection(d.geometry.coordinates) + ")"; })
.attr("dy", ".35em")
.attr("x", function(d) { return projection(d.geometry.coordinates)[0] <= width / 2 ? -6 : 6; })
.style("text-anchor", function(d){ return projection(d.geometry.coordinates)[0] <= width / 2 ? "end" : "start"; })
.text(function(d) { return d.properties.name; });
}
function drawSubUnits(data,scores){
var scoreByName = {};
scores.forEach(function(d) { scoreByName[d.name] = +d.value; });
g.selectAll(".subunit")
.data(topojson.feature(data, data.objects.collection).features)
.enter().append("path")
.attr("id",function(d) { return d.properties.NAME_1; })
.attr("class", function(d) { return 'subunit '+ d.properties.NAME_1; })
.attr("d", path)
.style("fill", function(d) { return color(scoreByName[d.properties.NAME_1]); })
.style("opacity", 0.8);
g.selectAll(".subunit-bg")
.data(topojson.feature(data, data.objects.collection).features)
.enter().append("rect")
.attr("rx", 3)
.attr("ry", 3)
.attr("x", -15)
.attr("y", -23)
.attr("width", 30)
.attr("height", 25)
.attr("transform", function(d) { return "translate(" + path.centroid(d) + ")"; })
.attr("dx", function (d) { return d.properties.dx || "0"; })
.attr("dy", function (d) { return d.properties.dy || "0.35em"; })
.style("fill", 'white')
.attr('opacity', '0.8')
//.attr('stroke', '#000')
//.attr('stroke-width', '1')
//.attr('shape-rendering','crispEdges')
;
g.selectAll(".subunit-label")
.data(topojson.feature(data, data.objects.collection).features)
.enter().append("text")
.attr("class", function(d) { return "subunit-label " + d.id; })
.attr("transform", function(d) { return "translate(" + path.centroid(d) + ")"; })
.attr("dx", function (d) { return d.properties.dx || "0"; })
.attr("dy", function (d) { return d.properties.dy || "-0.35em"; })
.text(function(d) { return scoreByName[d.properties.NAME_1]; });
}
// Create legend
var legend = d3.legendColor()
.labelFormat(d3.format(",.0f"))
.cells(10)
.scale(color);
var div = d3.select("body").append("div")
.attr("id", "legend");
var svg = div.append("svg");
svg.append("g")
.attr("class", "legendQuant")
.attr("transform", "translate(20,20)");
svg.select(".legendQuant")
.call(legend);
</script>
</body>
</html>
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment