← Examples
districts · region filter · topojson · choropleth · fips join

Massachusetts Counties

Fetching only Massachusetts counties using filter=US-MA — 14 features, pruned to the arcs of this state rather than the full US dataset. The choropleth joins 2020 census population data to each county via its gid, which is the 5-digit FIPS code used by Census, BLS, CDC, and most US federal data sources.

API Call

https://api.mapjson.com/v1/geo?layer=districts&filter=US-MA&detail=medium

Code

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Massachusetts Counties</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: #d4cfc8; }
    svg { width: 100%; height: 100vh; display: block; }
    .county { stroke: #f4efe8; stroke-width: 0.5; }
    .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>
    // 2020 Census population keyed by FIPS gid — joins directly to Census/BLS/CDC data
    const population = {
      "25001": 213444,  // Barnstable
      "25003": 154518,  // Berkshire
      "25005": 569048,  // Bristol
      "25007": 17535,   // Dukes (Martha's Vineyard)
      "25009": 801077,  // Essex
      "25011": 71372,   // Franklin
      "25013": 470490,  // Hampden
      "25015": 160830,  // Hampshire
      "25017": 1632002, // Middlesex
      "25019": 14255,   // Nantucket
      "25021": 722023,  // Norfolk
      "25023": 521202,  // Plymouth
      "25025": 803907,  // Suffolk (Boston)
      "25027": 857591,  // Worcester
    };

    const url = "https://api.mapjson.com/v1/geo?layer=districts&filter=US-MA&detail=medium";

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

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

    const color = d3.scaleSequential()
      .domain([0, d3.max(Object.values(population))])
      .interpolator(d3.interpolateBlues);

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

      const projection = d3.geoMercator()
        .fitExtent([[40, 40], [width - 40, height - 40]], geojson);
      const path = d3.geoPath().projection(projection);

      svg.selectAll("path")
        .data(geojson.features)
        .join("path")
        .attr("class", "county")
        .attr("d", path)
        .attr("fill", d => color(population[d.properties.gid] || 0))
        .on("mousemove", function(event, d) {
          const pop = population[d.properties.gid];
          tooltip.style.left = (event.clientX + 12) + "px";
          tooltip.style.top  = (event.clientY - 10) + "px";
          tooltip.style.opacity = 1;
          tooltip.innerHTML =
            `<strong>${d.properties.name}</strong><br>` +
            `gid: ${d.properties.gid}<br>` +
            `population: ${pop ? pop.toLocaleString() : "—"}`;
        })
        .on("mouseleave", () => { tooltip.style.opacity = 0; });
    });
  </script>
</body>
</html>