D3JS缩放和过渡性能

5
我有一些关于D3中地图缩放和平移的代码,但是性能非常差。在缩放和平移时,刷新需要近3秒时间。我认为将所有县/市的线条边界包括在内会让地图看起来更好,但是6MB+的数据可能正是瓶颈所在。是否有其他处理转换的方式,或者优化地图数据的方法?D3是否不适用于这种详细级别?我对D3非常陌生。
我正在使用从此处下载的shape文件,使用QGIS从DBF格式转换为Geojson: https://www.census.gov/cgi-bin/geo/shapefiles2010/main
<!doctype html>
<html>

<head>
   <title>d3 map</title>
   <script src="http://d3js.org/d3.v3.min.js">
   </script>
</head>

<body>
   <script>
            var width = 800;
            var height = 600;

            var projection = d3.geo.mercator();
            var path = d3.geo.path().projection (projection);

            var canvas = d3.select ("body")
               .append ("svg")
               .attr ("width", width)
               .attr ("height", height)

            var zoomVar = d3.behavior.zoom()
               .translate(projection.translate())
               .scale(projection.scale())
               .scaleExtent([height, 60 * height])
               .on("zoom", onPostZoom);

            var hotbox = canvas.append("g").call(zoomVar);

            hotbox.append("rect")
               .attr("class", "background")
               .attr("width", width)
               .attr("fill", "white")
               .attr("height", height);     

            d3.json ("cali.geojson", function (data) 
            {
               hotbox.append("g")
                  .attr("id", "geometry")
                  .selectAll("path")
                  .data(data.features)
                     .enter()
                        .append("path")
                        .attr("d", path)
                        .attr("fill", "steelblue")
                        .on("click", onClick);

            })




function onClick (d) 
{
   var centroid = path.centroid(d), translate = projection.translate();

   projection.translate(
   [translate[0] - centroid[0] + width / 2,
    translate[1] - centroid[1] + height / 2 ]);

   zoomVar.translate(projection.translate());

   hotbox.selectAll("path").transition()
      .duration(700)
      .attr("d", path);

}     


function onPostZoom() 
{
  projection.translate(d3.event.translate).scale(d3.event.scale);
  hotbox.selectAll("path").attr("d", path);
}

</script>
</body>
</html>
2个回答

10

正如Lars所说,你应该将数据简化到适当的分辨率。根据你想要缩放的程度选择最大的分辨率。我建议使用topojson -s进行简化,因为你还可以获得更小的TopoJSON格式的优势。

另一个重要的事情是如果只是平移和缩放,请避免重新投影。重新投影是一种相对昂贵的三角函数操作,而在SVG中序列化非常大的路径字符串也是如此。你可以通过在路径元素或包含的G元素上简单地设置变换属性来避免这种情况。参见以下示例:

你还应该考虑使用投影的TopoJSON备用示例),它将投影嵌入到TopoJSON文件中。这使得客户端速度更快:它永远不需要进行投影!


我需要使用TopoJSON地图文件格式才能使用D3 topojson函数,对吗?(..还需要一个可用的Linux topojson转换实用程序...)nm:只是在查看您有用的“替代示例”,这证实了这一点。 - wufoo
D3没有任何“TopoJSON函数”。相反,您可以使用topojson命令行工具(适用于Linux)将您的shapefile或GeoJSON转换为TopoJSON文件。然后,您可以使用topojson.js客户端库将其转换回浏览器中的GeoJSON,以便您可以使用D3或其他库进行渲染。 - mbostock
啊,好的,这样就清楚了一些,谢谢。对于任何有兴趣的人来说,在Ubuntu 12.04上安装topojson是相当困难的。Ubuntu上的一些捆绑依赖项会发生冲突,所以我按照以下两个链接进行了安装:https://github.com/NarrativeScience/Log.io/issues/63 http://milkator.wordpress.com/2013/02/23/installing-topojson-on-ubuntu-12-04/ - wufoo

4

您遇到的问题并不是由于D3,而是由于浏览器。主要的瓶颈在于呈现所有视觉元素,而不是计算它们的位置等。

避免这种情况的唯一方法就是减少数据量。一个开始的方法是使用QGIS中的边界简化,例如使用dpsimplify插件。


1
值得一提的是,还可以考虑使用 TopoJSON,它可以处理简化并使用更小的格式。 - nrabinowitz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接