D3.js 数据映射坐标到 topojson 地图上

D3.js data mapping coordinates onto a topojson map

我一直在尝试将坐标转换为我用 d3 和 topojson 制作的 svg 地图上的 "cx" 和 "cy" 位置。我在网上找到了很多解决方案,但似乎无法让它发挥作用。我正在尝试使用我的投影函数转换我的 json 文件中给出的纬度和经度坐标,但它似乎 return 每次计算都返回 null。

无视

//var geocoder = new google.maps.Geocoder();
//console.log(geocoder);
//figure out how to fix
//setIntervalAPI(alumni, geocoder, 1000);
console.log("Test");

  //size of canvas
  var width = 960,
  height = 500,
  centered;

  //projection of the svg
  var projection = d3.geo.albersUsa()
      .scale(1070)
      .translate([width / 2, height / 2]);

  //lines for projection
  var path = d3.geo.path()
      .projection(projection)
      .pointRadius(1.5);

  //scalable object svg
  var svg = d3.select("#usa").append("svg")
      .attr("width", width)
      .attr("height", height);

  //elements of the svgs
  svg.append("rect")
      .attr("class", "background")
      .attr("width", width)
      .attr("height", height)
      .on("click", clicked); //for click to zoom function

  //adds a group class for the svg
  var g = svg.append("g");


  //queues json files to load
  queue()
    .defer(d3.json, "https://gist.githubusercontent.com/mbostock/4090846/raw/d534aba169207548a8a3d670c9c2cc719ff05c47/us.json") // Load US Counties
    .defer(d3.json, "https://script.googleusercontent.com/macros/echo?user_content_key=K1E85EiRkGvkNnkwdiT6jmlX9xSU6hUvetLTNzpCcd_jSC2GpNbwZfr0KcbLfJdiHrUouVDeG7bCkVA0V_Fi5YMBTitaxVEdOJmA1Yb3SEsKFZqtv3DaNYcMrmhZHmUMWojr9NvTBuBLhyHCd5hHa1ZsYSbt7G4nMhEEDL32U4DxjO7V7yvmJPXJTBuCiTGh3rUPjpYM_V0PJJG7TIaKp1q6LyBxbset-sbB7gU77AXzTewdOjiNZcuPDH50tUN-GOHXQiXJz0ANQ8AP0ES9ozQJv8DXWa1hoIgY-huuTFg&lib=MbpKbbfePtAVndrs259dhPT7ROjQYJ8yx")
    .await(ready); // Run 'ready' when JSONs are loaded

  function ready(error, usa, alumni){
    if(error) throw error;
    console.log(usa);
    console.log(alumni.Form1);

    //var geocoder = new google.maps.Geocoder();
    //console.log(geocoder);
    //figure out how to fix
    //setIntervalAPI(alumni, geocoder, 1000);
    console.log("Test");


    g.append("g")
      .attr("id", "states")
    .selectAll("path")
      .data(topojson.feature(usa, usa.objects.states).features)
    .enter().append("path")
      .attr("d", path)
      .on("click", clicked);

    g.append("path")
      .datum(topojson.mesh(usa, usa.objects.states, function(a, b) { return a !== b; }))
      .attr("id", "state-borders")
      .attr("d", path);

    /** appends circles to the map
    NEEDS FIXED
    */
    g.selectAll("circle")
      .data(alumni.Form1).enter()
      .append("circle")
      .attr("cx", function(d) { return projection(d.lat)})
      .attr("cy", function(d) {//console.log(projection(d.lng));
        return projection(d.lng)})
      .attr("r", "8px")
      .attr("fill", "blue");

这是我的 json 文件结构的示例。出于尊重,我已经删除了个人信息,但 lng 和 lat 是我正在尝试转换的。

{
        "timestamp": "",
        "name": "",
        "location": "Austin, TX",
        "current_company": "",
        "current_position": "",
        "company_logo": "",
        "ta_start":,
        "ta_role": "",
        "favorite_memory": "",
        "how_ta_helped": "Always have a side hustle. ",
        "picture": "",
        "personal_handles": "",
        "linkedin": "",
        "lng": 30.267153,
        "lat": 97.7430607999999
    }

我最终找到了问题的解决方案。我发现

var projection = d3.geo().albersUsa()
   .scale(1070)
   .translate([width / 2, height / 2]);
当提供的坐标相对于 svg 地图超出范围时,

变量将 return 为 null。我相信投影也需要一对坐标,而不仅仅是一个坐标。所以我最终改变了

.attr("cx", function(d){ 
        return projection(d.lat)
})

.attr("cx", function(d) {
        var c = [d.lat, d.lng];
        var p = projection(c);
        console.log(p);
        return p[0]
}) 

这最终解决了我的绘图问题。然后我想改变我将圆圈附加到我的 svg 的方式,因为一旦坐标问题得到解决,它就会出错。

这是固定的解决方案

g.selectAll("svg")
      .data(alumni.Form1).enter().append("svg:circle")
      .attr("cx", function(d) {
        var c = [d.lat, d.lng];
        p = projection(c);
        console.log(p);
        return p[0]
      })
      .attr("r", 2.5)
      .attr("cy", function(d){
        var c = [d.lat, d.lng];
        p = projection(c);
        return p[1]
      })
      .style("fill", "blue"); 

我希望这对遇到类似问题的人有所帮助