【问题标题】:Drawing already projected geoJSON map in d3.js在 d3.js 中绘制已经投影的 geoJSON 地图
【发布时间】:2013-02-01 12:47:43
【问题描述】:

使用 d3.js 的 v3 时,我在使用 geoJSON 数据绘制地图时遇到问题。代码和生成的地图显示在:http://bl.ocks.org/73833ec90a8a77b0e29f。此示例使用 d3.js 的 v2 生成正确的地图。

  1. 我的数据已经被投影(它们是荷兰国家电网/Rijksdriehoekstelsel 坐标)。为了弥补这一点,我编写了自己的投影函数,它只是将地图的坐标系转换为像素(例如缩放和平移)。
  2. d3.js v3 中的 d3.geo.path() 重新采样数据。但是,重采样中生成的点似乎与我的地图不在同一个坐标系中(我假设它们是 lon、lat 坐标)。

我不希望将我的地图坐标转换为 lon、lat 坐标,因为地图已经按照我想要的方式投影,而且据我所知,这不是一个简单的投影。

如果问题确实是由重采样引起的,我想禁用重采样。但是,在文档中我真的找不到如何做到这一点。我可以传递一个流对象,而不是将投影函数传递给 d3.geo.path.projection()。我认为以下方法会起作用:

var projection = d3.geo.projection(function(x, y) {
    return [ scale*(x-xmin), height-scale*(y-ymin) ];
  }).precision(0);

但事实并非如此。可能也与我没有纬度,经度坐标的事实有关。如何使用自定义投影功能禁用重采样?

或者当其他原因导致问题时,我想听听。

谢谢。

【问题讨论】:

    标签: d3.js geojson


    【解决方案1】:

    我最近遇到了同样的问题。

    这样做的方法是明确告诉 d3 你不想要投影。 答案就在这个link

    "If projection is null, the path uses the identity transformation, where the input 
    geometry is not projected and is instead rendered directly in raw coordinates. This can be 
    useful for fast rendering of already-projected geometry, or for fast rendering of the 
    equirectangular projection."
    

    所以你想拥有

    var path = d3.geo.path().projection(null);
    

    然后,像这样

    g.selectAll("path")
                .data(json.features)
                .enter().append("path")
                .attr("d", path)
    

    【讨论】:

    • 谢谢。我已经看到了,但我遇到的问题是我需要缩放和翻译我的地图(原始坐标以米为单位,距离北海某处的某个点)。也许使用 NULL 投影并使用 scale 和 translate 方法会起作用。我会告诉你它是否有效。
    • 我无法让您的解决方案发挥作用。但是,我找到了另一种解决方案。
    【解决方案2】:

    针对 user603124 的回答,我重新审视了这个问题(直到现在我坚持使用 d3.js 的 v2)。我最初创建对象的想法有效。但是,在我最初的实现中,我的缩放和缩放错误。使用answer to another question 获得正确的缩放和缩放:

    <script>
      var height = 400;
      var width  = 400;
    
      var vis = d3.select("#vis").append("svg")
          .attr("width", width).attr("height", height)
    
      d3.json("po_2012_simplified.json", function(json) {
    
          var projection = d3.geo.projection(function(x, y) { return [x, y];})
            .precision(0).scale(1).translate([0, 0]);
    
          var path = d3.geo.path().projection(projection);
    
          var bounds = path.bounds(json),
              scale  = .95 / Math.max((bounds[1][0] - bounds[0][0]) / width, 
                      (bounds[1][1] - bounds[0][1]) / height),
              transl = [(width - scale * (bounds[1][0] + bounds[0][0])) / 2, 
                      (height - scale * (bounds[1][1] + bounds[0][1])) / 2];
    
          projection.scale(scale).translate(transl);
    
          vis.selectAll("path").data(json.features).enter().append("path")
            .attr("d", path)
            .style("fill", "#D0D0D0")
            .style("stroke-width", "0.5px")
            .style("stroke", "black")
        });
    
    </script>
    

    请参阅http://bl.ocks.org/djvanderlaan/5336035 了解完整的工作解决方案。

    【讨论】:

    • 这真是太好了!我喜欢您使用d3.geo.projection(function(x, y) { return [x, y];}) 的解决方案。为什么每个人都希望他们所有的最终用户(观众)动态地重新投影数据,这超出了我的理解。在 99% 的地图中,我看到动态重新投影完全没有用,而且浪费了计算能力。
    • d3.geo.projection 用于将球坐标转换为笛卡尔坐标。如果您只想在笛卡尔坐标中进行缩放和平移,我建议您使用 d3.geo.transform 而不是 bl.ocks.org/5663666
    猜你喜欢
    • 2014-07-20
    • 2015-06-18
    • 1970-01-01
    • 2017-07-24
    • 2018-08-24
    • 2012-08-14
    • 2017-10-09
    • 1970-01-01
    相关资源
    最近更新 更多