13

我正在玩 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 )编辑 (现在可以在https://github.com/alignedleft/d3-book/releases/tag/v1.0的 zip 下载文件中找到文件)在阿尔伯斯投影中并修改为采用印度的 Geojson(下面的 indiastates1.json)。该代码适用于美国文件,但不显示任何印度 json 文件。我在这里错过了什么吗。任何帮助表示赞赏。我确实将投影更改为墨卡托。

<!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]]]}}
]}
4

3 回答 3

11

您(或浏览器)只是在错误的地方寻找。我认为 d3 通过这些地理预测自动以美国为中心。您需要做的就是使用变换将“印度”移动到 svg 视口。具体来说,您需要将视口的原点转换为以 x,y 像素为单位的坐标指定的位置——或者至少我是这么认为的。为了看印度,我试过了

.attr("transform", "translate(-800,200)")

它似乎完成了这项工作。

如果您检查元素,很容易找到这些东西,然后您可以使用路径为您提供一些转换位置的提示。

更新

解决此问题的更好方法是计算中心和比例,如本问题和答案中所述。特别是 Jan 和 Mike 的回答都非常出色。在这个谷歌小组讨论中也有对代码的解释——倒数第二篇。

于 2013-08-25T07:31:12.273 回答
2

这是一个简单的示例,展示了如何将地图投影围绕要素集合中的所有要素(不仅仅是一个要素或默认要素)居中,它基于链接的 Mike Bostock 答案,这很好,但基于仅缩放一个要素,还有d3.js geoJSON 和 bounds表明可以使用整个特征集合。

对代码的主要更改是:

  • 用中性替换初始平移和缩放:

       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>
于 2016-07-24T13:20:38.587 回答
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);
于 2015-07-03T18:11:58.207 回答