在调整规范示例时,我的topojson不会显示

aba*_*oru 3 geojson d3.js topojson

我开始研究D3以创建一个按年过滤的等值/热图.

问题:

我想显示这个topojson文件.我试图在这里调整Mike Bostock的topojson示例.但是,当我为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; })));
}); 
Run Code Online (Sandbox Code Playgroud)

And*_*eid 5

问题

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

地理坐标不会完全落在这个范围内.

为什么没有画画?

与示例不同,您的topojson要素包含地理坐标 - 纬度和经度.

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

您没有对功能应用必要的投影.使用geoPath时,通常需要指定geoProjection:

var path = d3.geoPath().projection(d3.geoProjection)
Run Code Online (Sandbox Code Playgroud)

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

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

南半球的价值观具有负值,因此它们也将从屏幕上消失.在这种情况下,在svg或画布上方 - 因为y值在屏幕顶部从零开始,随着向下移动而增加.

最后,如果你在地球的东北象限中有任何特征,它们会出现,因为它们的坐标是正的(假设你的svg高90像素,宽180像素).但是,它们会颠倒过来,因为随着人们向上"移动"地图,y值会增加,但是在svg/canvas坐标空间中,当人们向上"移动"地图时,它们会减少.

解决问题

您需要使用投影.最基本的设置可能是使用像墨卡托这样的简单投影,并使用fitSize或fitExtent自动缩放和居中显示您想要显示的特征.为此,您可以使用以下内容:

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

// once topojson is loaded:
projection.fitSize([width,height],geojson object);
Run Code Online (Sandbox Code Playgroud)

你如何获得geojson?你已经是:

topojson.feature(aisp, aisp.objects.convert)  // convert topojson to geojson.
Run Code Online (Sandbox Code Playgroud)

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

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

这种方法没有设定投影的更复杂的参数,例如旋转或锥形投影,例如Albers,平行线,但在许多情况下它就足够了.

以下是使用fitSize(我更改了文件名)的地图示例.