D3: Mappa coropletica - Proiezioni

    <style>
.country:hover {
    stroke: #b64;
    stroke-width: 1px;
}
</style>

<script>
let svg = d3.select("body").append("svg")
            .attr("width",670).attr("height",350)

let margin = { top: 0, right: 0, bottom: 0, left: 40 }
let graphWidth = 670 - margin.left - margin.right
let graphHeight = 350 - margin.top - margin.bottom

let graph = svg.append("g")
               .attr("transform", "translate("+margin.left+","+margin.top+")")

let projection = d3.geoNaturalEarth1()
projection.translate([graphWidth/2, graphHeight/2])
          .scale(projection.scale() * (graphHeight/500))
let pathGenerator = d3.geoPath().projection(projection)

Promise.all([
    d3.json("https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/world.geojson"),
    d3.tsv("https://unpkg.com/world-atlas@1.1.4/world/50m.tsv")
]).then(function([geoData, tsvData]) {
            
    let countryIncomes = {}
    tsvData.forEach(d => {
        countryIncomes[d.iso_a3] = d.income_grp
    })

    let incomeGroups = []
    tsvData.forEach(d => {
        if (!incomeGroups.includes(d.income_grp)) {
            incomeGroups.push(d.income_grp)
        }
    })
                
    let colorScale = d3.scaleOrdinal()
        .domain(incomeGroups.sort())
        .range(d3.schemeBlues[incomeGroups.length+1].slice().reverse())

    graph.selectAll(".country")
         .data(geoData.features)
         .join("path")
         .attr("class", "country")
         .attr("d", pathGenerator)
         .attr("fill", d => {
             let incomeGroup = countryIncomes[d.id]
             return incomeGroup ? colorScale(incomeGroup) : "#bbb"
          })
         .append("title")
         .text(d => {
             let countryName = d.properties.name
             let incomeGroup = countryIncomes[d.id] || "Unclassified"
             return countryName + ":\n" + incomeGroup
          })

    let legendY = svg.attr("height") - incomeGroups.length*18 - 20
    let legend = svg.append("g")
                    .attr("class", "legend")
                    .attr("transform", "translate(10, " + legendY + ")")

    incomeGroups.forEach((group, i) => {
        let legendRow = legend.append("g")
            .attr("transform", "translate(0, " + (i*18) + ")")

        legendRow.append("rect")
                 .attr("width", 15)
                 .attr("height", 15)
                 .attr("fill", colorScale(group))

        legendRow.append("text")
                 .attr("x", 22)
                 .attr("y", 12)
                 .style("font-family", "sans-serif")
                 .style("font-size", "12px")
                 .text(group)
    })
})
</script>    
    
  

Viene creata un’istanza della modalità di proiezione cartografica pseudocilindrica “Natural Earth” (d3.geoNaturalEarth1()).
La proiezione viene centrata all’interno del gruppo graph e, visto che le impostazioni predefinite si riferiscono a una dimensione complessiva di 960x500 pixel, la scala viene adattata alla risoluzione del gruppo con la mappa (projection.scale() * (graphHeight/500)).

La proiezione viene usata per impostare le trasformazioni del generatore di sagome creato con il metodo d3.geoPath().

Usare una diversa modalità di visualizzazione provando fra le proiezioni di d3.js, ad esempio:
    d3.geoEquirectangular()
oppure
    d3.geoOrthographic()