【问题标题】:D3.Geo performance on Pan/ZoomD3.Pan/Zoom 上的 Geo 性能
【发布时间】:2013-06-10 05:23:59
【问题描述】:

去年我使用Mapnik library(服务器端,位图/平铺)在网络地图上做了几个实验。现在我正在尝试使用带有 d3.js 的矢量客户端方法来复制相同的实验。

我有一张地图(约 680 个形状),其中zoom 很慢,pan 很慢(Mike Bostock 的this example 效果很好)。我怀疑问题出在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 here):

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

[更新]

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

【问题讨论】:

    标签: d3.js gis topojson


    【解决方案1】:

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

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

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

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

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

    【讨论】:

    • 你让我走上了正轨。平底锅有点颠簸,因为翻译是在移动的同一元素上计算的,但我想我可以解决这个问题;稍微编辑了你的答案(d3.event.translate 是一个数组),希望你不介意。
    • 较短的 "translate(" + d3.event.translate + ")" 之所以起作用,是因为 javascript 如何处理数组和字符串的添加,但这对于长度来说可能有点太笨拙/不清楚减少?祝你好运!
    • 你是对的。未完成的编辑,最好在另一个答案中发布对我有用的内容。谢谢!很有帮助。
    • 另请注意,我认为您需要添加一个“g”元素来对地图的内容进行分组并对其进行转换 - 直接将转换应用于 svg 对象似乎不起作用。
    • 当我平移它时,如果它在视口中变得不可见,因为我们拖得太多,那么如何将它拖回视口? This example 有这样的行为,但我使用的是上面的例子,而不是按照建议做 selectAll。
    【解决方案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) 必须在 maps 父元素中,否则平移/缩放会变得颠簸。

    【讨论】:

      【解决方案3】:

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

      颂歌示例:

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

      JSFiddle

      【讨论】:

      • 你有没有将这种剪裁机制应用到地图上?
      猜你喜欢
      • 2013-03-07
      • 2013-06-17
      • 1970-01-01
      • 2014-05-12
      • 2020-10-21
      • 1970-01-01
      • 1970-01-01
      • 2023-02-09
      • 1970-01-01
      相关资源
      最近更新 更多