2013-08-25 5 views
12

Ich spiele um Geo-Module von D3. Ich habe etwas Erfahrung mit D3, aber das ist das erste Mal, dass ich die Geo-Module ausprobiere. Ich habe den folgenden Code (von https://github.com/alignedleft/d3-book/blob/master/chapter_12/04_fill.html) entnommen, das ursprünglich zeigt US-Karte (https://github.com/alignedleft/d3-book/edit/master/chapter_12/us-states.json) bearbeiten in albers Projektion und modifizierte nehmen eine GeoJSON von Indien (indiastates1 (Dateien können nun in der Zip-Datei runterladen in https://github.com/alignedleft/d3-book/releases/tag/v1.0 finden). JSON unten). Der Code funktioniert gut mit der US-Datei, aber zeigt nichts mit Indien JSON-Datei. Fehle ich hier etwas. Jede Hilfe wird geschätzt. Ich habe allerdings die Projektion in Mercator geändert.Anzeige der Karte mit d3.js und geojson

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

Antwort

10

Sie sind (oder der Browser) einfach nur an der falschen Stelle. Ich denke, dass sich d3 mit diesen Geo-Projektionen automatisch auf die USA konzentriert. Alles, was Sie tun müssen, ist die Transformation, um 'Indien' in das Svg-Ansichtsfenster zu verschieben. Insbesondere müssen Sie den Ursprung des Ansichtsfensters an einen Ort übertragen, der durch Koordinaten in x, y Pixeln angegeben wird - oder zumindest so, wie ich es mir vorstelle. Um Indien zu sehen versuchte ich

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

und es schien die Arbeit zu tun.

Es ist ziemlich einfach, diese Dinge auszuwählen, wenn Sie das Element untersuchen, Sie können dann den Pfad verwenden, um Ihnen einige Hinweise zu geben, wo Sie transformieren können.

UPDATE

Ein weitaus besserer Ansatz ist es, dieses Problem in die Mitte und Maßstab zu berechnen wäre wie in diesen question and answer skizzierte. Insbesondere die Antwort von Jan und Mike ist hervorragend. Es gibt auch eine Erklärung des Codes in diesem google groups discussion - der vorletzte Beitrag.

+0

Vielen Dank. Ich habs. Ich vermutete auf ähnliche Weise auch, wie auf Chrom, weil Konsole keine Fehler geworfen und wenn ich Svg auf Elemente geklickt habe, scheint es irgendwo im Browser zu markieren, wusste aber nicht wo! Es ging also darum, die richtige Transformation zu finden, um sie zu verlagern. Hast du versucht, die richtigen Zahlen für die Transformation zu finden? –

+1

Der Pfad (d. H. Das Bit nach d = das geht M150.158 128.215, 486.1589Z) sagt Ihnen, wo es angezeigt wird. Die Zahlen in diesem Beispiel zeigen an, dass der Pfad eine 150 beginnt, in Ihrem Beispiel war die erste Zahl ungefähr 900, also habe ich einfach das Ansichtsfenster -800 und ein wenig nach unten verschoben, da der Inspektor es nur nach oben zeigte des Bildschirms. Für eine vollständigere Antwort versuche [this] (http://stackoverflow.com/questions/14492284/center-a-map-in-d3-given-a-geojson-object) – user1614080

0

Dieses Problem tritt auf, weil die US-Karte so positioniert ist, dass sie die USA zentriert. Sie haben wahrscheinlich die Indien-Datei geladen, aber es kann aus dem Bildschirm oder sehr klein zu sehen sein. Sie können die Korrektur manuell vornehmen, indem Sie die Werte für Maßstab und Mittelpunkt ändern und übersetzen. aber eine bessere Lösung zu finden, wird automatisch die Skalierung und Übersetzung aus dem Code

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); 
2

Dies ist ein einfaches Beispiel zeigt, wie um all die Features in der Feature-Sammlung Ihre Kartenprojektion zum Zentrum (nicht nur ein oder die Standard), es basiert auf der linked Mike Bostock answer, die groß ist, aber basierend auf Zoomen auf nur eine Funktion, und auch d3.js geoJSON and bounds, die zeigt, dass ganze Feature-Sammlungen verwendet werden können.

Die wichtigsten Änderungen am Code sind:

  • die anfängliche übersetzen und Skala mit einem neutralen einem Ersetzen:

    var projection = d3.geo.mercator() 
         .scale(1) 
         .translate([0, 0]); 
    
  • Nach dem Laden der json, Code hinzufügen, den Vorsprung dynamisch zu aktualisieren basierend auf der Bounding-Box von die gesamte Feature-Sammlung:

So ist das neueste Fassung der gesamte Beispiel würde wie folgt aussehen:

<!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>