D3 避免投影超出框架的数据

问题描述

我正在处理一个涉及大型可缩放地图的 D3 项目。一切看起来都不错,工作正常,只是当我缩放和平移时,视图会变得有点滞后。

我想知道 D3 是否有办法让我避免投影超出框架的地图数据。如果可能的话,我想在不牺牲细节的情况下提高性能。任何提示提示将不胜感激!

解决方法

这里有几个选项。我会将这个问题概括为优化使用 d3 显示大量地理数据的方法。

projection.clipExtent(extent)

此方法采用一个数组来标记特征绘制范围的左上角和右下角(在投影/像素坐标空间中)。要素被裁剪到指定的范围。每个点仍然贯穿投影,但您不必绘制它们或沿边缘进行大圆采样。严格来说,这与问题的要求很接近。

projection.clipAngle(angle)

上述方法适用于投影空间,而此方法适用于未投影空间。此方法采用一个表示角度(以度为单位)的值,并根据该角度和投影的旋转中心裁剪要素。根据您的投影,旋转可能是平移和居中地图的合适方法。您必须计算给定缩放级别和居中的最大裁剪角度,然后在投影到裁剪角度指定的小圆圈之前裁剪地图。这通过避免在裁剪之前投影点的需要来改善上述情况,但由于小圆圈很少符合视口,因此会绘制超出所需范围的一些特征(尽管少得多)。以上可以结合这种方法。

可以制作自定义预剪裁功能以获得更好的效果。这对于圆柱投影来说比其他投影更容易,以便在投影之前将特征裁剪到指定的框,从而提高效率。

其他选项

  • 矢量瓷砖

矢量磁贴可从多种来源获得 - 尽管我并不特别关心 d3-tile(我一直在研究替代方案,但太忙而无法真正专注于它)。您仍然需要在每次缩放时加载图块,并在每次平移时加载一些图块,但此选项可为您提供最大范围的细节和适当的数据分辨率。

  • 边界框

上述方法的替代方法是在每个多边形上存储边界框信息(不要即时进行)。在绘制地图时,过滤那些与视口有任何重叠的多边形将只启用相关要素的选择性渲染。根据投影和缩放机制,这可以在投影或非投影坐标空间中完成。

这可以通过以两个或更多比例加载特征来补充:缩小所有特征都被绘制而不管可见性,但在缩小时以适当的分辨率绘制。当放大超过一定深度时,使用更详细的特征,但基于边界框过滤。

  • 画布

我在这里包含这个只是因为 SVG 有时可能是关键点,这取决于绘制的要素数量和类型。改用 Canvas 可能是我的改进。

  • 投影类型

投影类型确实会影响速度,等距柱状投影很快,一些方位角投影很慢。虽然我只在任何 detail 中测试过 projection.invert(),但投影类型是一个因素。

预投影几何是最快的,它完全绕过了投影:特征坐标空间以像素为单位。有关该主题的更多信息,请参阅 here

结合边界框方法和/或基于当前范围进行裁剪的函数,这可能是一种非常快速的方法。

  • 缩放事件

我根据您的问题文本添加了这一点:投影功能应该在放大或不放大的同时进行。绘图可能是可变的,但投影以任何一种方式运行。这表明您可能正在使用 .on("zoom" 事件。这不是很有效:平移事件的每个刻度都需要重新绘制,换句话说,单个平移可以触发许多缩放事件。这意味着您需要在平移期间几乎不断地投影特征。

对此的一个简单解决方案是使用 .on("end" 事件作为重绘地图的事件。这样我们每次缩放只重绘一次地图。

但是,您可以变得更复杂。如果您希望地图在整个平移事件中跟随鼠标移动,您可以使用变换来平移地图,避免投影任何内容,然后在缩放结束时重新投影地图并移除变换。这几乎肯定需要重新考虑您的缩放功能。在确定是否发生平移以避免在缩放比例不变 (example) 时重绘集群之前,我采用了某种类似的方法。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...