3

去年,我使用Mapnik 库(服务器端、位图/平铺)对 web 地图进行了几次实验。现在我正在尝试使用带有 d3.js 的向量客户端方法来复制相同的实验。

我有一张地图(约 680 个形状),zoom速度很慢而且pan很迟钝( Mike Bostock 的这个例子效果很好)。我怀疑问题出在zoommove回调中,selectAll("path").attr("d", path)耗时太长。

function zoommove() {
    projection.translate(d3.event.translate).scale(d3.event.scale);
    mapa.selectAll("path").attr("d", path);
    console.log('zoommove fired...');
}

问题

  1. 我在这里做错了吗?
  2. 我该怎么做才能优化性能?

地图是这样的(这里是 jsfiddle):

巴西圣保罗州的自治市

数据源为 topojson 格式。它被简化了,可能已经太多了,因为有些形状没有关闭:

在此处输入图像描述

[更新]

看起来即使在没有简化标志的情况下运行 topojson 时也会出现开放几何的问题,我仍在调查。我会很感激这里的任何线索,文档不是很详细。

4

3 回答 3

11

(我不太确定这里发生了什么,这可能是完全错误的)。

mapa.selectAll("path").attr("d", path);

从头开始重新绘制地图。这适用于 50 个州,但对于 600 多个形状开始变得相当缓慢。如果您将路径留在原处并仅转换整个 svg,您可能会有更好的运气:

function zoommove() {
  svg.attr("transform",
      "translate("+d3.event.translate+")"
      + " scale("+d3.event.scale+")");
}

我用它来创建美国的县级地图(约 500 个形状),可以平滑地缩放和平移。

于 2013-06-13T18:58:28.453 回答
2

在这里回答我自己的问题,如果您觉得这有帮助,请改为支持亚当的回答,他值得称赞。

什么对我有用:

var bg = svg.append('g')
    .call(zoom);

var map = bg.append("g")
    .attr("transform", "translate(0,0) scale(1)");

...

function zoommove() {
    var t1 = projection.translate(),
        t2 = d3.event.translate,
        t = [t2[0]-t1[0], t2[1]-t1[1]];

    map.attr("transform", 
        "translate("+t+") " +
        "scale("+(d3.event.scale/s)+")"
    );
    console.log(map.attr("transform"));
}

一些技巧:

  • 如果projection.translate()不是[0, 0],则必须考虑到它,否则在您第一次尝试平移/缩放时(仅第一次)会发生很大的颠簸。
  • 如果projection.scale()不是 1,则必须将其考虑在内。
  • .call(zoom)必须在地图父元素中,否则平移/缩放会变得颠簸。
于 2013-06-13T22:26:07.440 回答
1

我遇到过类似的问题,并且重新缩放不适合我的解决方案,因为我不希望缩放 svg 元素本身。相反,我所做的是对其进行优化,以便不重新计算可见区域之外的元素。这意味着当所有元素都在视图中时性能仍然很差,但是当你放大它时会好得多。

颂歌样本:

clippedArea.selectAll("circle")
    .style("visibility", d => pointInDomain(d, domain) ? "visible" : "hidden")
    .filter(d => pointInDomain(d, domain))
  .attr("cx", d => xz(d.x));

JSFiddle

于 2017-06-26T00:55:33.987 回答