You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

D3投影函数转换经纬度返回NaN问题排查(CSV映射GeoJSON地图)

D3 v5中d3.geoAlbers()转换机场经纬度返回NaN的解决方法

常见问题及修复步骤

  • 经纬度未转为数值类型:CSV读取的字段默认是字符串,d3.geoAlbers()需要数值类型的坐标。处理数据时要把经纬度字段转为数字:

    const cleanedAirportData = airportData.map(d => ({
      ...d,
      longitude: Number(d.longitude),
      latitude: Number(d.latitude)
    }));
    
  • 坐标顺序错误:D3地理投影遵循GeoJSON标准,要求坐标格式为[经度, 纬度],但CSV数据常以纬度, 经度的顺序存储。如果代码里传的是[纬度, 经度],会直接返回NaN,调整顺序即可:

    // 错误写法
    // projection([d.latitude, d.longitude])
    // 正确写法
    projection([d.longitude, d.latitude])
    
  • 过滤无效坐标:检查CSV中是否存在空值、超出±180/±90范围的经纬度值,这类无效值会导致投影转换失败。处理阶段可过滤掉:

    const validAirports = cleanedAirportData.filter(d => {
      return !isNaN(d.longitude) && !isNaN(d.latitude) &&
             d.longitude >= -180 && d.longitude <= 180 &&
             d.latitude >= -90 && d.latitude <= 90;
    });
    
  • 复用投影实例:确保绘制地图和机场点使用同一个d3.geoAlbers()实例,不要重新创建未配置参数的投影对象:

    // 初始化并配置投影
    const projection = d3.geoAlbers()
      .fitSize([width, height], usGeoJson);
    
    // 绘制地图(复用projection)
    svg.append("g")
      .selectAll("path")
      .data(usGeoJson.features)
      .enter().append("path")
      .attr("d", d3.geoPath().projection(projection));
    
    // 绘制机场点(复用同一个projection)
    svg.selectAll(".airport")
      .data(validAirports)
      .enter().append("circle")
      .attr("cx", d => projection([d.longitude, d.latitude])[0])
      .attr("cy", d => projection([d.longitude, d.latitude])[1])
      .attr("r", 2)
      .style("fill", d => stateColorScale(d.stateAbbr));
    

调试技巧

添加日志打印单个机场的坐标和投影结果,快速定位问题:

console.log("原始数据:", airportData[0]);
console.log("转换后坐标:", [Number(airportData[0].longitude), Number(airportData[0].latitude)]);
console.log("投影结果:", projection([Number(airportData[0].longitude), Number(airportData[0].latitude)]));

内容的提问来源于stack exchange,提问作者Palucca

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 03:31:05