使用d3.js和geojson显示地图

时间:2013-08-25 03:39:55

标签: d3.js

我正在玩D3的地理模块。我对D3有一些经验,但这是我第一次尝试使用地理模块。我已经采用了以下代码(来自https://github.com/alignedleft/d3-book/blob/master/chapter_12/04_fill.html),该代码最初显示的是美国地图(https://github.com/alignedleft/d3-book/edit/master/chapter_12/us-states.json编辑 (现在可以在{{ 3}})在albers投影中并修改为带印度的Geojson(indiastates1.json)。该代码适用于US文件,但不显示任何与印度json文件。 我在这里错过了一些东西。任何帮助表示赞赏。我确实将投影改为mercator。

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>D3: Setting path fills</title>
        <script type="text/javascript" src="../d3/d3.v3.js"></script>
        <style type="text/css">
            /* No style rules here yet */       
        </style>
    </head>
    <body>
        <script type="text/javascript">

            //Width and height
            var w = 500;
            var h = 300;

            //Define map projection
            var projection = d3.geo.mercator()
                                   .translate([w/2, h/2])
                                   .scale([500]);

            //Define path generator
            var path = d3.geo.path()
                             .projection(projection);

            //Create SVG element
            var svg = d3.select("body")
                        .append("svg")
                        .attr("width", w)
                        .attr("height", h);

            //Load in GeoJSON data
            d3.json("indiastates1.json", function(json) {

                //Bind data and create one path per GeoJSON feature
                svg.selectAll("path")
                   .data(json.features)
                   .enter()
                   .append("path")
                   .attr("d", path)
                   .style("fill", "steelblue");

            });

        </script>
    </body>
</html>

indiastates1.json

{"type":"FeatureCollection","features":[
{"type":"Feature","id":"IND","properties":{"name":"India"},"geometry":{"type":"Polygon","coordinates":[[[77.837451,35.49401],[78.912269,34.321936],[78.811086,33.506198],[79.208892,32.994395],[79.176129,32.48378],[78.458446,32.618164],[78.738894,31.515906],[79.721367,30.882715],[81.111256,30.183481],[80.476721,29.729865],[80.088425,28.79447],[81.057203,28.416095],[81.999987,27.925479],[83.304249,27.364506],[84.675018,27.234901],[85.251779,26.726198],[86.024393,26.630985],[87.227472,26.397898],[88.060238,26.414615],[88.174804,26.810405],[88.043133,27.445819],[88.120441,27.876542],[88.730326,28.086865],[88.814248,27.299316],[88.835643,27.098966],[89.744528,26.719403],[90.373275,26.875724],[91.217513,26.808648],[92.033484,26.83831],[92.103712,27.452614],[91.696657,27.771742],[92.503119,27.896876],[93.413348,28.640629],[94.56599,29.277438],[95.404802,29.031717],[96.117679,29.452802],[96.586591,28.83098],[96.248833,28.411031],[97.327114,28.261583],[97.402561,27.882536],[97.051989,27.699059],[97.133999,27.083774],[96.419366,27.264589],[95.124768,26.573572],[95.155153,26.001307],[94.603249,25.162495],[94.552658,24.675238],[94.106742,23.850741],[93.325188,24.078556],[93.286327,23.043658],[93.060294,22.703111],[93.166128,22.27846],[92.672721,22.041239],[92.146035,23.627499],[91.869928,23.624346],[91.706475,22.985264],[91.158963,23.503527],[91.46773,24.072639],[91.915093,24.130414],[92.376202,24.976693],[91.799596,25.147432],[90.872211,25.132601],[89.920693,25.26975],[89.832481,25.965082],[89.355094,26.014407],[88.563049,26.446526],[88.209789,25.768066],[88.931554,25.238692],[88.306373,24.866079],[88.084422,24.501657],[88.69994,24.233715],[88.52977,23.631142],[88.876312,22.879146],[89.031961,22.055708],[88.888766,21.690588],[88.208497,21.703172],[86.975704,21.495562],[87.033169,20.743308],[86.499351,20.151638],[85.060266,19.478579],[83.941006,18.30201],[83.189217,17.671221],[82.192792,17.016636],[82.191242,16.556664],[81.692719,16.310219],[80.791999,15.951972],[80.324896,15.899185],[80.025069,15.136415],[80.233274,13.835771],[80.286294,13.006261],[79.862547,12.056215],[79.857999,10.357275],[79.340512,10.308854],[78.885345,9.546136],[79.18972,9.216544],[78.277941,8.933047],[77.941165,8.252959],[77.539898,7.965535],[76.592979,8.899276],[76.130061,10.29963],[75.746467,11.308251],[75.396101,11.781245],[74.864816,12.741936],[74.616717,13.992583],[74.443859,14.617222],[73.534199,15.990652],[73.119909,17.92857],[72.820909,19.208234],[72.824475,20.419503],[72.630533,21.356009],[71.175273,20.757441],[70.470459,20.877331],[69.16413,22.089298],[69.644928,22.450775],[69.349597,22.84318],[68.176645,23.691965],[68.842599,24.359134],[71.04324,24.356524],[70.844699,25.215102],[70.282873,25.722229],[70.168927,26.491872],[69.514393,26.940966],[70.616496,27.989196],[71.777666,27.91318],[72.823752,28.961592],[73.450638,29.976413],[74.42138,30.979815],[74.405929,31.692639],[75.258642,32.271105],[74.451559,32.7649],[74.104294,33.441473],[73.749948,34.317699],[74.240203,34.748887],[75.757061,34.504923],[76.871722,34.653544],[77.837451,35.49401]]]}}
]}

3 个答案:

答案 0 :(得分:10)

你(或浏览器)只是看错了地方。我认为d3通过这些地理预测自动集中在美国。您需要做的就是使用transform将'India'移动到svg视口。具体来说,您需要将视口的原点转换为x,y像素坐标指定的位置 - 或者至少是我想到的方式。看到印度我试过

.attr("transform", "translate(-800,200)")
它似乎完成了这项工作。

如果检查元素,那么选择这些内容非常容易,然后可以使用该路径为您提供转换的提示。

<强>更新

更好的方法是这个问题是计算中心和比例,如question and answer中所述。特别是Jan和Mike的答案都非常出色。此google groups discussion中的代码也有解释 - 最后一篇文章。

答案 1 :(得分:2)

这是一个简单的示例,展示如何围绕所有功能集合中的功能(不仅仅是一个或默认值)围绕地图投影,它基于{{3 }},这很棒,但只基于一个特征的缩放,还有linked Mike Bostock answer,表明可以使用整个特征集。

您的代码的主要更改是:

  • 用中性的替换初始翻译和缩放:

       var projection = d3.geo.mercator()
           .scale(1)
           .translate([0, 0]);
    
  • 加载json后,添加代码以根据整个要素集的边界框动态更新投影:

       var b = path.bounds( json ),
       s = .95 / Math.max((b[1][0] - b[0][0]) / w, (b[1][1] - b[0][1]) / h),
       t = [(w - s * (b[1][0] + b[0][0])) / 2, (h - s * (b[1][1] + b[0][1])) / 2];
    
       projection
            .scale(s)
            .translate(t);
    

因此更新的完整示例如下所示:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>D3: Setting path fills</title>
        <script type="text/javascript" src="../d3/d3.v3.js"></script>
        <style type="text/css">
            /* No style rules here yet */       
        </style>
    </head>
    <body>
        <script type="text/javascript">

            //Width and height
            var w = 500;
            var h = 300;

            //Define map projection
            var projection = d3.geo.mercator()
                                   .translate([0, 0])
                                   .scale(1);

            //Define path generator
            var path = d3.geo.path()
                             .projection(projection);

            //Create SVG element
            var svg = d3.select("body")
                        .append("svg")
                        .attr("width", w)
                        .attr("height", h);

            //Load in GeoJSON data
            d3.json("indiastates1.json", function(json) {

                // Calculate bounding box transforms for entire collection
                var b = path.bounds( json ),
                s = .95 / Math.max((b[1][0] - b[0][0]) / w, (b[1][1] - b[0][1]) / h),
                t = [(w - s * (b[1][0] + b[0][0])) / 2, (h - s * (b[1][1] + b[0][1])) / 2];

                // Update the projection    
                projection
                  .scale(s)
                  .translate(t);


                //Bind data and create one path per GeoJSON feature
                svg.selectAll("path")
                   .data(json.features)
                   .enter()
                   .append("path")
                   .attr("d", path)
                   .style("fill", "steelblue");

            });

        </script>
    </body>
</html>

答案 2 :(得分:0)

发生此问题是因为美国地图的位置是为了使美国居中。 您可能已经加载了India文件,但它可能不在屏幕上或非常小。 您可以通过更改比例和居中和平移值来手动进行修正。 但更好的方法是自动从代码中找到比例和翻译

var b = path.bounds(#data#),
                s = .95 / Math.max((b[1][0] - b[0][0]) / width, (b[1][1] - b[0][1]) / height),
                 //scaled the bounding box 
                t = [(width - s * (b[1][0] + b[0][0])) / 2, (height - s * (b[1][1] + b[0][1])) / 2];
// new projection
              projection = d3.geo.mercator()
                             .scale(s).translate(t);
              path = path.projection(projection);