用d3覆盖传单上的圆圈会导致位置不正确 [英] Overlaying circles on leaflet with d3 results in not positioned properly

查看:81
本文介绍了用d3覆盖传单上的圆圈会导致位置不正确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用circlesd3覆盖leaflet映射.

<!DOCTYPE html>

<html lang="en">

<head>
<meta charset="utf-8">
<title>D3 Test</title>
<link rel="stylesheet" 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;">
    <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;


            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", 100)
                .style("fill", "red")
                .attr("fill-opacity", 0.5);

            function update() {
                circles.attr("cx", function(d) {
                    return map.latLngToLayerPoint(d.LatLng).x;
                });
                circles.attr("cy", function(d) {
                    return map.latLngToLayerPoint(d.LatLng).y;
                });
            }

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

        })
    </script>
</body>

</html>

circles已添加到DOM,但未显示在传单上.我想这是因为它们的位置不对. 那就是它的样子:

The circles are added to DOM, but do not show up on leaflet. I suppose its because they are positioned wrong. Thats how it looks like:

我如何正确定位它们?注意:我不想使用map._initPathRoot();来拾取leaflet创建的svg-element.

How would I position them correct? Note: I dont want to use map._initPathRoot(); to pick up the svg-element created by leaflet.

推荐答案

首先,您在这些圆上的半径太大了.您的JSON文件中有成千上万个点,每个点的半径为100px,并且地图只有600x600px.

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.

第二,似乎您正在尝试遵循本教程,但是您要离开了出一个关键的部分. Bostock先生讨论了如何计算特征的边界框以将SVG放置在正确的位置.您已经省去了这部分,因此将SVG放置在默认大小的0,0上.

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.

在他的教程中包含您的数据之后,将产生以下代码. 注意,我将您的JSON数据限制在东北的几个城市.我不想找到托管6mb JSON的地方(您可能想考虑将文件缩减到 only 个美国城市).

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 rel="stylesheet" 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>

回应评论

因为我将数据限制在较小的城市子集(纽约州和宾夕法尼亚州的城市)中,所以边界仅根据数据中的内容进行计算. 您的JSON中的所有城市都在这里(等待加载) .

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:

这篇关于用d3覆盖传单上的圆圈会导致位置不正确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆