代码之家  ›  专栏  ›  技术社区  ›  abaporu

修改规范示例时,我的topojson不会显示

  •  3
  • abaporu  · 技术社区  · 7 年前

    我开始研究D3,以便每年创建一个带有过滤器的choropleth/heatmap。

    问题:

    我想展示这个 topojson 文件我尝试改编MikeBostock的topojson示例 here . 然而,当我为topojson改编示例时,控制台中不会显示任何内容,也不会显示任何错误。

    我的代码如下所示:

    var svg = d3.select("svg");
    var path = d3.geoPath();
    d3.json("aisp.topojson", function(error, aisp) {
      if (error) throw error;
    
    svg.append("g")
      .attr("class", "states")
    .selectAll("path")
     .data(topojson.feature(aisp, aisp.objects.convert).features)
    .enter().append("path")
    .attr("d", path);
    
    
    svg.append("path")
      .attr("class", "state-borders")
      .attr("d", path(topojson.mesh(aisp, aisp.objects.convert, function(a, b) { return a !== b; })));
    }); 
    
    1 回复  |  直到 7 年前
        1
  •  5
  •   Andrew Reid    7 年前

    问题

    将此块用作示例可能会有问题,因为它不使用投影。该示例使用了一个预投影的topojson,其坐标位于像素坐标空间中-它被设计为显示在900 x 600像素窗口上,输入文件中的坐标值范围在[0,0]和[900600]的边界框内。因此,本示例不使用地理投影。

    地理坐标不会完全在此范围内。

    为什么什么都不画?

    与示例不同,topojson特性包含地理坐标-纬度和经度。

    要在d3或任何其他框架或程序中投影地理特征,必须应用投影将三维坐标空间中的地理坐标转换为适合显示在二维svg或画布网格上的平面笛卡尔坐标。

    您没有对要素应用必要的投影。使用地质路径时,通常需要指定地质投影:

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

    但是,您不使用投影,因此d3默认为空投影。对于topojson/geojson中的每个坐标,输入的x和y值都作为像素坐标,不进行变换/转换/缩放。

    由于要素位于西半球,因此x(经度)值为负值。x值为负值的像素位于屏幕左侧。

    南半球的值为负值,因此它们也将从屏幕上绘制出来。在这种情况下,在svg或画布上方-因为y值从屏幕顶部的零开始,并随着向下移动而增加。

    最后,如果您在地球的东北象限中有任何特征,它们将显示为正坐标(假设您的svg高90像素,宽180像素)。但是,它们是颠倒的,因为y值随着地图的“向上”移动而增加,但在svg/画布坐标空间中,它们随着地图的“向上”移动而减少。

    解决问题

    您需要使用投影。最基本的设置可能是使用简单的投影,如墨卡托投影,并使用fitSize或fitExtent自动缩放和居中显示要显示的特征。为此,您可以使用以下方法:

    var projection = d3.geoMercator();
    var path = d3.geoPath().projection(projection);
    
    // once topojson is loaded:
    projection.fitSize([width,height],geojson object);
    

    如何获取geojson?您已经是:

    topojson.feature(aisp, aisp.objects.convert)  // convert topojson to geojson.
    

    您需要传递的是geojson对象,而不是它包含的特性数组,因此我们不使用 topojson.feature(aisp, aisp.objects.convert).features 具有fitSize。

    FitSize获取宽度和高度,并设置投影的比例并转换为适当的值。FitExtent采用两个点标记要素边界框的左上角和右下角: projection.fitExtent([[x1,y1],[x2,y2]],geojson);

    这种方法不会设置更复杂的投影参数,如旋转或锥形投影参数,如反照率、平行度,但在许多情况下,它已经足够了。

    实例

    Here's 使用fitSize的地图示例(我更改了文件名)。