2013-08-25 13 views
12

Sto giocando attorno ai moduli geografici di D3. Ho una certa esperienza con D3 ma questa è la prima volta che provo i moduli geografici. Ho preso il seguente codice (da https://github.com/alignedleft/d3-book/blob/master/chapter_12/04_fill.html) che consente di visualizzare in origine mappa degli Stati Uniti (https://github.com/alignedleft/d3-book/edit/master/chapter_12/us-states.json) modifica(file possono ora essere trovate nel scaricabile zip in https://github.com/alignedleft/d3-book/releases/tag/v1.0) in Albers proiezione e modificato per tenere un GeoJSON dell'India (indiastates1. json sotto). Il codice funziona bene con il file USA, ma non mostra nulla con il file json India. Mi manca qualcosa qui. Qualsiasi aiuto è apprezzato. Ho però cambiato la proiezione su Mercator.Visualizzazione della mappa con d3.js e 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]]]}} 
]} 

risposta

10

Sei (o il browser) solo guardando nel posto sbagliato. Penso che d3 si concentri automaticamente sugli Stati Uniti con queste proiezioni geografiche. Tutto quello che devi fare è usare la trasformazione per spostare "India" nella vista di svg. In particolare, è necessario tradurre l'origine della finestra in una posizione specificata dalle coordinate in x, y pixel - o almeno è così che la penso. Per vedere l'India ho provato

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

e sembrava fare il lavoro.

È facile scegliere queste cose se si ispeziona l'elemento, è quindi possibile utilizzare il percorso per darvi alcuni suggerimenti su dove trasformare.

UPDATE

Un approccio molto migliore è a questo problema sarebbe quella di calcolare il centro e la scala come descritto in questo question and answer. In particolare, la risposta di Jan e Mike sono entrambe eccellenti. C'è anche una spiegazione del codice in questo google groups discussion - il penultimo secondo.

+0

Grazie mille. Fatto. Sospetto anche su linee simili, come su chrome, perché la console non ha lanciato alcun errore e quando ho cliccato su elementi svg, sembra evidenziarlo da qualche parte sul browser ma non sapevo dove! Quindi era questione di trovare la giusta trasformazione per trasferirla. Hai fatto tentativi ed errori nel trovare i numeri giusti per la trasformazione? –

+1

Il percorso (ovvero il bit dopo d = che va a M150.158 128.215, 486.1589Z) indica dove viene visualizzato. I numeri in questo esempio indicano che il percorso inizia a 150, nel tuo esempio penso che il primo numero fosse circa 900, quindi ho solo spostato il viewport -800 e un po 'più in basso mentre l'ispettore lo mostrava in cima dello schermo. Per una risposta più completa prova [this] (http://stackoverflow.com/questions/14492284/center-a-map-in-d3-given-a-geojson-object) – user1614080

0

Questo problema si verifica perché la mappa degli Stati Uniti è posizionata in modo da centrare gli Stati Uniti. Probabilmente hai caricato il file India ma potrebbe essere fuori dallo schermo o molto piccolo da vedere. È possibile eseguire manualmente la correzione modificando i valori di scala e centro e tradurre. ma un approccio migliore è trovare automaticamente la scala e la traduzione dal codice

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

Questo è un semplice esempio che mostra come per centrare la vostra proiezione cartografica intorno tutte le caratteristiche della tua collezione di elementi (non solo uno o le predefinito), si basa sullo linked Mike Bostock answer, che è ottimo ma basato sullo zoom su una sola funzione e anche su d3.js geoJSON and bounds che mostra che è possibile utilizzare intere raccolte di funzioni.

Il tasto al codice sono:

  • Sostituzione iniziale tradurre e scala con una neutra uno:

    var projection = d3.geo.mercator() 
         .scale(1) 
         .translate([0, 0]); 
    
  • Dopo aver caricato il json, aggiungendo codice per aggiornare dinamicamente la proiezione in base al riquadro di delimitazione di dell'intera collezione di elementi:

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

Così l'esempio completo aggiornato sarebbe simile a questa:

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