2016-10-03 9 views
1

Ich versuche, Punkte zu einer Karte hinzuzufügen, indem ich die -Bibliothek verwende. (Ich habe versucht, ein Skript von diesem gist anzupassen).SVG-Elemente über vorhandene Elemente anhängen

Das Problem ist, dass die Karte über den Punkten gerendert wird. Ich habe versucht, eine andere SO-Antwort zu verwenden, die so etwas vorgeschlagen hat: svg.append("g").attr("id", "map").attr("id", "points") ... aber ich konnte es nicht funktionieren lassen. Ich bin eine lange Zeit Python Benutzer ... JavaScript ist neu für mich (also bitte entschuldigen Sie die Naivität).

ist das folgende CSS:

<style> 
    body { 
     background-color: white; 
    } 
    svg { 
     border: 1px solid black; 
     background-color: #a4bac7; 
    } 
     .land { 
      fill: #d7c7ad; 
      stroke: #8999ab; 
     } 
     .boundary { 
      fill: none; 
      stroke: #a5967f; 
     } 
    </style> 

Körper:

<script type="text/javascript" src="d3/d3.js"></script> 
    <script src="http://d3js.org/topojson.v0.min.js"></script> 

    <script> 
     var width = 960; 
     var height = 480; 
     var dataURL = "https://gist.githubusercontent.com/abenrob/787723ca91772591b47e/raw/8a7f176072d508218e120773943b595c998991be/world-50m.json"; 

     var svg = d3.select("body").append("svg") 
      .attr("width", width) 
      .attr("height", height); 

Als Reaktion auf this SO Antwort beantworten, diese hinzugefügt:

 svg.append("g") 
       .attr("id", "map") 
       .attr("id", "points"); 

 var projection = d3.geoEquirectangular() 
      .scale(153) 
      .translate([width/2,height/2]) 

     var path = d3.geoPath() 
      .projection(projection); 

     d3.json(dataURL, function(error, world) { 
      svg.append("g") 
       .select("#map").selectAll(".map") 
       .attr("class", "land") 
       .selectAll("path") 
       .data([topojson.object(world, world.objects.land)]) 
       .enter().append("path") 
       .attr("d", path); 
      svg.append("g") 
       .select("#map").selectAll(".map") 
       .attr("class", "boundary") 
       .selectAll("boundary") 
       .data([topojson.object(world, world.objects.countries)]) 
       .enter().append("path") 
       .attr("d", path); 
      } 
     ); 

     var lngLatExtract = function(d, i){ 
      return projection([d['lng'], d['lat']])[i]; 
     }; 

     d3.csv("cities.csv", function(data){ 
       svg.append("g") 
         .select("#points").selectAll(".points") 
         .data(data) 
         .enter() 
          .append('circle') 
          .attr("cx", function(d){ 
           return lngLatExtract(d, 0); 
          }) 
          .attr('cy', function(d){ 
           return lngLatExtract(d, 1); 
          }) 
          .style("fill", "blue") 
          .style("opacity", 0.75) 
          .attr("r", function(d){ 
           return Math.sqrt(parseInt(d['population']) * 0.000001) 
          }); 
       } 
     ); 

    </script> 

cities.csv sieht wie folgt aus:

rank,place,population,lat,lng 
1,New York city,8175133,40.71455,-74.007124 
2,Los Angeles city,3792621,34.05349,-118.245323 

Antwort

2

Sowohl d3.json und d3.csv sind async Funktionen. Die Reihenfolge, in der ihre Callbacks ausgelöst werden, ist nicht gegeben und da Ihre CSV-Datei kleiner ist, wird der Callback wahrscheinlich zuerst ausgelöst. Das bedeutet, dass Ihre svg.append("g") in Ihrem csv-Callback vor der svg.append("g") im JSON-Callback geschieht. Sie können dies bestätigen, indem Sie das DOM überprüfen und sehen, welches zuerst angehängt wurde.

Das sagte, ich würde zu d3.queue wechseln. Auf diese Weise können Sie sowohl die asynchronen Anforderungen d3.json als auch die auslösen und dann einen einzigen Rückruf auslösen, wenn beide abgeschlossen sind.

Eine andere weniger rationalisierte Option ist, Ihren Code in den Rückruf des d3.json Anrufs zu platzieren.

Verwandte Themen