block by enjalot eaf648eb5fd33a59b3865d8fc4f5eade

WWSD #10: Leaflet + d3 overlay

Full Screen

Working with spatial data

Example #10

Adding a d3.js overlay to a Leaflet map. Inspired by Mike Bostock’s tutorial.

Built with blockbuilder.org

forked from enjalot‘s block: WWSD #1: Leaflet starter

index.html

<!DOCTYPE html>
<head>
  <meta charset="utf-8">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
  <script src="//d3js.org/topojson.v1.min.js"></script>
  <link rel="stylesheet" href="//cdn.leafletjs.com/leaflet/v0.7.7/leaflet.css" />
   <script src="//cdn.leafletjs.com/leaflet/v0.7.7/leaflet.js"></script>
  
  <style>
    body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
    #map {
      position:absolute; 
      width: 100%;
      height: 100%;
    }
    
    path {
      fill-opacity: 0.3;
      stroke: #111;
    }
    
  </style>
</head>

<body>
  <div id="map"></div>
  <script>
    var map = L.map('map').setView([53, -3], 6);

    L.tileLayer('//{s}.tile.osm.org/{z}/{x}/{y}.png', {
        attribution: '&copy; <a href="//osm.org/copyright">OpenStreetMap</a> contributors'
    }).addTo(map);
    
    // Setup our svg layer that we can manipulate with d3
    var svg = d3.select(map.getPanes().overlayPane)
      .append("svg");
    var g = svg.append("g").attr("class", "leaflet-zoom-hide");
    
    function leafletProjection(lnglat) {
      var point = map.latLngToLayerPoint(L.latLng(lnglat.reverse()))
      return [point.x, point.y]
    }
    
    var path = d3.geo.path()
      .projection(leafletProjection)
    
    var url = "//enjalot.github.io/wwsd/data/UK/counties.topojson"
    d3.json(url, function(err, topo) {
      console.log("topojson", topo)
      var counties = topojson.feature(topo, topo.objects.lad)
      
      var countyPaths = g.selectAll("path").data(counties.features)
      countyPaths.enter().append("path")
      countyPaths.attr("d", path)
      
      function render() {
        // We need to reposition our SVG and our containing group when the map
        // repositions via zoom or pan
        // https://github.com/zetter/voronoi-maps/blob/master/lib/voronoi_map.js
        var bounds = map.getBounds();
        var topLeft = map.latLngToLayerPoint(bounds.getNorthWest())
        var bottomRight = map.latLngToLayerPoint(bounds.getSouthEast())
        svg.style("width", map.getSize().x + "px")
          .style("height", map.getSize().y + "px")
          .style("left", topLeft.x + "px")
          .style("top", topLeft.y + "px");
        g.attr("transform", "translate(" + -topLeft.x + "," + -topLeft.y + ")");

        // We reproject our data with the updated projection from leaflet
        countyPaths.attr("d", path)

      }

      // re-render our visualization whenever the view changes
      map.on("viewreset", function() {
        render()
      })
      map.on("move", function() {
        render()
      })

      // render our initial visualization
      render()
    })
    
  </script>
</body>