← Examples
countries · world · areakm2 · choropleth · Equal Earth

Country Area

World countries colored by land area using the areakm2 property — an opt-in field computed from 10m Natural Earth geometry. A logarithmic color scale handles the range from Vatican City (0.44 km²) to Russia (17M km²). Hover to see each country's area. areakm2 is most useful as a denominator: divide any count by area to get a per-km² density.

API Call

https://api.mapjson.com/v1/geo?layer=countries&filter=world&detail=low&properties=name,areakm2

Code

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Country Area</title>
  <script src="https://cdn.jsdelivr.net/npm/d3@7/dist/d3.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/topojson-client@3/dist/topojson-client.min.js"></script>
  <style>
    body { margin: 0; background: #18303f; }
    svg { width: 100%; height: 100vh; display: block; }
    .country { stroke: #2e4a5a; stroke-width: 0.3; transition: opacity 0.1s; }
    .country:hover { opacity: 0.8; }
    .graticule { fill: none; stroke: #2e5870; stroke-width: 0.3; }
    .sphere { fill: #22485e; }
    .tooltip {
      position: fixed;
      background: #2c2317;
      color: #f4efe8;
      font-family: monospace;
      font-size: 11px;
      padding: 6px 10px;
      pointer-events: none;
      opacity: 0;
      transition: opacity 0.1s;
      line-height: 1.6;
    }
  </style>
</head>
<body>
  <div class="tooltip" id="tooltip"></div>
  <svg id="map"></svg>
  <script>
    const url = "https://api.mapjson.com/v1/geo?layer=countries&filter=world&detail=low&properties=name,areakm2";

    const width = 960, height = 500;
    const tooltip = document.getElementById("tooltip");

    const svg = d3.select("#map").attr("viewBox", `0 0 ${width} ${height}`);

    const projection = d3.geoEqualEarth()
      .scale(160).translate([width / 2, height / 2 + 20]);

    const path = d3.geoPath(projection);

    // Log scale — Russia (17M km²) is 40,000× larger than tiny island states
    const color = d3.scaleSequentialLog(d3.interpolateYlOrBr)
      .domain([500, 17000000]);

    svg.append("path").datum({type:"Sphere"})
      .attr("class", "sphere").attr("d", path);
    svg.append("path").datum(d3.geoGraticule()())
      .attr("class", "graticule").attr("d", path);

    d3.json(url).then(topo => {
      const geojson = topojson.feature(topo, topo.objects.geo);

      svg.selectAll(".country")
        .data(geojson.features)
        .join("path")
        .attr("class", "country")
        .attr("d", path)
        .attr("fill", d => d.properties.areakm2 ? color(d.properties.areakm2) : "#3a4a52")
        .on("mousemove", function(event, d) {
          const area = d.properties.areakm2;
          tooltip.style.left = (event.clientX + 12) + "px";
          tooltip.style.top  = (event.clientY - 10) + "px";
          tooltip.style.opacity = 1;
          tooltip.innerHTML =
            `<strong>${d.properties.name || d.properties.gid}</strong><br>` +
            (area ? area.toLocaleString() + " km²" : "area unavailable");
        })
        .on("mouseleave", () => { tooltip.style.opacity = 0; });
    });
  </script>
</body>
</html>