隐形载体?组合 d3.tile()、d3.zoom() 和 TopoJSON 向量

Invisible vectors? Combining d3.tile(), d3.zoom() and TopoJSON vectors

我使用栅格(d3.tile 和地图库)和矢量(SVG 形状中的 TopoJSON)制作了有效的 D3 地图。但是我在组合它们的时候遇到了一个错误。

我遵循了 Mike Bostock 的光栅和矢量示例,尤其是他的 "Raster & Vector III",它更改了变换和描边宽度以更新矢量的显示方式。

我的地图几乎完美无缺。但是,在加载时,只显示光栅图块;矢量是不可见的:

但是一旦我触发 d3.zoom 事件(通过平移或缩放),就会显示矢量:

我不明白这一点,因为我明确告诉浏览器,独立于缩放事件,绘制矢量。这是相关的片段:

  // read in the topojson
  d3.json("ausElectorates.json", function(error, mapData) {
    if (error) throw error;

    var electorates = topojson.feature(mapData, mapData.objects.tracts);

    // apply a zoom transform equivalent to projection{scale,translate,center}
    map.call(zoom)
      .call(zoom.transform, d3.zoomIdentity
        .translate(mapWidth / 2, mapHeight / 2)
        .scale(1 << 12)
        .translate(-centre[0], -centre[1]));

    // draw the electorate vectors
    vector.selectAll("path")
      .data(electorates.features)
      .enter().append("path")
        .attr("class", "electorate")
        .attr("d", path);
  });

出于某种原因,d3.json() 函数的最后一行 -- .attr("d", path") -- 没有可视化向量。

Click here to see the map. Click here 访问完整代码及其使用的 TopoJSON。

我很想得到这方面的建议,这让我很困惑!

(PS 为省略地图图块、D3.js 库等的版权归属而道歉 - 我只是想尽量减少此示例的代码。)

它正在绘制矢量 - 但是,你不能仅仅依靠 d3 geoProjection 缩放和平移你的矢量,因为当你缩放时你将平移和缩放应用到路径本身 - 而不是投影:

  vector.selectAll("path")
    .attr("transform", "translate(" + [change.x, change.y] + ")scale(" + change.k + ")")
    .style("stroke-width", 1 / change.k);

由于您没有设置缩放和平移,因此在加载矢量时它们不会正确绘制。它们绘制得非常小 - 因为您的投影比例为 1/tau,翻译为 [0,0]。在页面加载时检查 svg 显示它们在那里,而且很小。

解决方案是在 map.call("zoom") 之前绘制矢量 - 这样您就可以在手动缩放之前在路径上应用基础变换(居中、变换和缩放):

// read in the topojson
d3.json("ausElectorates.json", function(error, mapData) {
if (error) throw error;

var electorates = topojson.feature(mapData, mapData.objects.tracts);

// draw the electorate vectors
vector.selectAll("path")
  .data(electorates.features)
  .enter().append("path")
    .attr("class", "electorate")
    .attr("d", path);

// apply a zoom transform equivalent to projection{scale,translate,center}
map.call(zoom)
  .call(zoom.transform, d3.zoomIdentity
    .translate(mapWidth / 2, mapHeight / 2)
    .scale(1 << 12)
    .translate(-centre[0], -centre[1]));
   });