It is showing the whole world projection boundaries, but is not showing the map of vietnam at the center. I will be creating multiple maps from humdata.org that and need each specified country maps at the center, but I cannot seem to figure it out.
Here is the code that I have been trying:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vietnam</title>
<style>
html,
body {
margin: auto;
width: 100%;
padding: 0;
height: 100%;
overflow: hidden;
font-size: 12px;
font-weight: bold;
font-family: arial;
position: absolute;
display: flex;
align-items: center;
text-align: center
}
path {
stroke: orange;
stroke-width: 0.15vw;
fill: black;
}
svg {
display: block;
margin: 0 auto;
font-size: 2vw;
font-family: arial;
font-weight: bolder;
border: 0px solid white;
}
</style>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="http://d3js.org/topojson.v0.min.js"></script>
<script src='https://unpkg.com/@turf/turf@6/turf.min.js'></script>
</head>
<body>
<script type="text/javascript">
d3.json("https://gist.githubusercontent.com/teglouis27/3c2fe0d34a64c91d04695f24530aa423/raw/7e7a91530b34234043995cd923a1cbc61f4fd4c6/vietnamCountryBorders").then(function(bb) {
let width = 700,
height = 700;
// Calculate the center of the country
let center = d3.geoCentroid(bb);
// Set up the projection to use the center
let projection = d3.geoEqualEarth().center(center);
// Scale and translate the projection to fit within the width and height
projection.fitSize([width, height], bb);
let geoGenerator = d3.geoPath().projection(projection);
let bounds = geoGenerator.bounds(bb);
let svg = d3.select("body").append('svg').attr("preserveAspectRatio", "xMinYMin meet").attr("viewBox", "0 0 700 700").style("width", width).style("height", height);
svg.append('g').selectAll('path').data(bb.features).join('path').attr('d', geoGenerator).attr('fill', '#088').attr('stroke', '#000');
});
</script>
</body>
</html>
I am still not sure how to fix it. Translating and scaling just moves the whole image. I figure I will need to use the convex hull from turtle.js, then subtract it from the original json file. But I am now trying to get the points by themselves so I can apply that.
When I import the file into https://mapshaper.org/, it shows exactly what I am trying to do.
The d3.geoPath().projection()
function does not center your map automatically, and projection.fitSize([width, height], bb)
will only scale your map to fit within the specified width and height.
To center your map, you will have to manually set the center of the projection. But before that, you need to calculate the center of your geoJSON data.
Here's how to do it:
d3.json("https://gist.githubusercontent.com/teglouis27/3c2fe0d34a64c91d04695f24530aa423/raw/7e7a91530b34234043995cd923a1cbc61f4fd4c6/vietnamCountryBorders").then(function(bb) {
let width = 1000, height = 1000;
// Calculate the center of the country
let center = d3.geoCentroid(bb);
// Set up the projection to use the center
let projection = d3.geoEqualEarth().center(center);
// Scale and translate the projection to fit within the width and height
projection.fitSize([width, height], bb);
let geoGenerator = d3.geoPath().projection(projection);
let bounds = geoGenerator.bounds(bb);
let svg = d3.select("body").append('svg').style("width", width).style("height", height);
svg.append('g').selectAll('path').data(bb.features).join('path').attr('d', geoGenerator).attr('fill', '#088').attr('stroke', '#000');
});
In this revised script, I've used the d3.geoCentroid()
function to calculate the geographic center of the country's boundaries, and then used this center to set up the projection.
Note: d3.geoCentroid()
calculates the geographic center of a geometry, which might not be the actual geometric center of the shape. However, for most uses, this is close enough.
Please also make sure that your JSON data is correct and properly formatted, otherwise the above script may not work as expected. It's always a good idea to verify your data and use console.log to debug where necessary.