Skip to content Skip to sidebar Skip to footer

Overlaying Circles On Leaflet With D3 Results In Not Positioned Properly

I want to overlay a leaflet map with circles through d3. D3 Test

Solution 1:

First, your radius on those circles is way too large. You have thousands of points in your JSON file each with a radius of 100px and your map is only 600x600px.

Second, it seems like you are attempting to follow this tutorial, but you are leaving out a key piece. Mr. Bostock talks about how to calculate the bounding box of your features to place your SVG in the right position. You've left this part out, so your SVG is being placed at 0,0 with a default size.

Following his tutorial with your data produces the following code. Note, I limited your JSON data to only a few cities in the north-east. I didn't want to find some place to host 6mb of JSON (you might want to think about cutting that file down to only US cities).

<!DOCTYPE html>

<html lang="en">

<head>
  <meta charset="utf-8">
  <title>D3 Test</title>
  <link  href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css">
  <script type="text/javascript" src="https://d3js.org/d3.v3.min.js"></script>
  <script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
</head>

<body>
  <div id="map" style="width:600px; height:600px;"></div>
  <script>
    var map = new L.Map("map", {
        center: [37.8, -96.9],
        zoom: 4
      })
      .addLayer(new L.TileLayer("http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"));

    var svg = d3.select(map.getPanes().overlayPane).append("svg"),
      svgCircles = svg.append("g").attr("class", "leaflet-zoom-hide");

    d3.json("https://jsonblob.com/api/580256bbe4b0bcac9f7ffa43", function(error, myPoints) {
      if (error) throw error;

      var transform = d3.geo.transform({
          point: projectPoint
        }),
        path = d3.geo.path().projection(transform);

      var bounds = path.bounds(myPoints),
        topLeft = bounds[0],
        bottomRight = bounds[1];

      myPoints.features.forEach(function(d) {
        d.LatLng = new L.LatLng(d.geometry.coordinates[1],
          d.geometry.coordinates[0]);
      });

      var circles = svgCircles.selectAll("circle")
        .data(myPoints.features)
        .enter()
        .append("circle")
        .attr("r", 10)
        .style("fill", "red")
        .attr("fill-opacity", 0.5);

      // Use Leaflet to implement a D3 geometric transformation.
      function projectPoint(x, y) {
        var point = map.latLngToLayerPoint(new L.LatLng(y, x));
        this.stream.point(point.x, point.y);
      }

      function update() {
        circles.attr("cx", function(d) {
          return map.latLngToLayerPoint(d.LatLng).x;
        });
        circles.attr("cy", function(d) {
          return map.latLngToLayerPoint(d.LatLng).y;
        });
        svg.attr("width", bottomRight[0] - topLeft[0])
          .attr("height", bottomRight[1] - topLeft[1])
          .style("left", topLeft[0] + "px")
          .style("top", topLeft[1] + "px");

        svgCircles.attr("transform", "translate(" + -topLeft[0] + "," + -topLeft[1] + ")");
      }

      map.on("viewreset", update);
      update();

    })
  </script>
</body>

</html>

RESPONSE TO COMMENTS

Because I limited the data to a smaller subset of cities (those in NY and PA) the bounds are only calculated to what's in the data. Here it is with all the cities in your JSON (wait a bit for it to load).

And a quick screenshot with all the data:

enter image description here


Post a Comment for "Overlaying Circles On Leaflet With D3 Results In Not Positioned Properly"