D3 避免投影超出框架的数据
D3 avoid projecting data that extends beyond the frame
我正在处理一个涉及大型可缩放地图的 D3 项目。一切看起来都很好并且工作正常,除了当我缩放和平移视图时可能会有点滞后。
我想知道 D3 是否有办法让我避免投影超出框架的地图数据。如果可能的话,我想在不牺牲细节的情况下提高性能。任何提示或技巧将不胜感激!
这里有几个选项。我将把这个问题概括为优化使用 d3 显示大量地理数据的方法。
projection.clipExtent(范围)
此方法采用一个数组,标记要素绘制范围的左上角和右下角(在 projected/pixel 坐标 space 中)。要素被裁剪到指定范围。每个点仍然 运行 通过投影,但您不必绘制它们或沿边缘进行大圆采样。严格来说,这已经接近问题的要求了。
projection.clipAngle(角度)
尽管上述方法适用于投影 space,但此方法适用于非投影 space。此方法采用表示角度(以度为单位)的值,并根据此角度和投影的旋转中心裁剪要素。根据您的投影,旋转可能是平移和居中地图的合适方法。您必须计算给定缩放级别和居中的最大裁剪角度,然后在投影到裁剪角度指定的小圆圈之前裁剪地图。这通过避免在裁剪之前投影点的需要对上述进行了改进,但由于小圆圈很少符合视口,因此绘制的某些特征会超出所需范围(尽管要少得多)。以上可以与这种方法结合使用。
可以自定义preclipping功能以获得更好的效果。这对于圆柱投影比其他投影更容易,以便在投影之前将特征裁剪到指定的框,这将提高效率。
其他选项
- 矢量瓷砖
可以从许多来源获得矢量图块 - 虽然我并不特别关心 d3-tile(我一直在研究替代方案,但太忙了,无法真正专注于它)。您仍然需要在每次缩放时加载图块,并在每次平移时加载一些图块,但此选项可为您提供最大范围的细节和适当的数据分辨率。
- 边界框
上述方法的替代方法是在每个多边形上存储边界框信息(不要即时进行)。绘制地图时,过滤那些与视口有任何重叠的多边形将启用仅相关要素的选择性渲染。根据投影和缩放机制,这可以在投影或非投影坐标 space.
中完成
这可以通过以两个或更多比例加载特征来补充:缩小所有特征都被绘制而不考虑可见性,但在缩小时以适当的分辨率绘制。当放大超过一定深度时,使用更详细的特征,但基于边界框进行过滤。
- Canvas
我把它包括在这里只是因为 SVG 有时可能是夹点,这取决于绘制的特征的数量和类型。切换到 Canvas 可以 是改进。
- 投影类型
投影类型确实影响速度,等角投影快,一些方位角投影慢。虽然我只在任何 中测试了 projection.invert()
,但投影类型是一个因素。
预投影几何是最快的,它完全绕过了投影:特征坐标 space 以像素为单位。有关该主题的更多信息,请参阅 。
结合边界框方法and/or根据当前范围裁剪的功能,这可能是一种非常快速的方法。
- 缩放事件
我根据你的问题的文字添加:投影功能应该同时放大或不放大。绘图可能是可变的,但投影 运行 是相同的。这表明您可能正在使用 .on("zoom"
事件。这不是很有效:平移事件的每个滴答声都需要重新绘制,换句话说,单个平移可能会触发许多缩放事件。这意味着您需要在平移过程中几乎不断地投射特征。
一个简单的解决方案是使用 .on("end"
事件作为重绘地图的事件。这样我们每次缩放只重绘一次地图。
但是,您可以变得更复杂。如果您希望地图在整个平移事件中跟随鼠标,您可以使用变换来平移地图,避免投影任何东西,然后在缩放结束时,重新投影地图并删除变换。这几乎肯定需要重新考虑您的缩放功能。在确定是否发生平移以避免在缩放比例未更改时重绘群集之前,我采用了某种类似的方法 (example)。
我正在处理一个涉及大型可缩放地图的 D3 项目。一切看起来都很好并且工作正常,除了当我缩放和平移视图时可能会有点滞后。
我想知道 D3 是否有办法让我避免投影超出框架的地图数据。如果可能的话,我想在不牺牲细节的情况下提高性能。任何提示或技巧将不胜感激!
这里有几个选项。我将把这个问题概括为优化使用 d3 显示大量地理数据的方法。
projection.clipExtent(范围)
此方法采用一个数组,标记要素绘制范围的左上角和右下角(在 projected/pixel 坐标 space 中)。要素被裁剪到指定范围。每个点仍然 运行 通过投影,但您不必绘制它们或沿边缘进行大圆采样。严格来说,这已经接近问题的要求了。
projection.clipAngle(角度)
尽管上述方法适用于投影 space,但此方法适用于非投影 space。此方法采用表示角度(以度为单位)的值,并根据此角度和投影的旋转中心裁剪要素。根据您的投影,旋转可能是平移和居中地图的合适方法。您必须计算给定缩放级别和居中的最大裁剪角度,然后在投影到裁剪角度指定的小圆圈之前裁剪地图。这通过避免在裁剪之前投影点的需要对上述进行了改进,但由于小圆圈很少符合视口,因此绘制的某些特征会超出所需范围(尽管要少得多)。以上可以与这种方法结合使用。
可以自定义preclipping功能以获得更好的效果。这对于圆柱投影比其他投影更容易,以便在投影之前将特征裁剪到指定的框,这将提高效率。
其他选项
- 矢量瓷砖
可以从许多来源获得矢量图块 - 虽然我并不特别关心 d3-tile(我一直在研究替代方案,但太忙了,无法真正专注于它)。您仍然需要在每次缩放时加载图块,并在每次平移时加载一些图块,但此选项可为您提供最大范围的细节和适当的数据分辨率。
- 边界框
上述方法的替代方法是在每个多边形上存储边界框信息(不要即时进行)。绘制地图时,过滤那些与视口有任何重叠的多边形将启用仅相关要素的选择性渲染。根据投影和缩放机制,这可以在投影或非投影坐标 space.
中完成这可以通过以两个或更多比例加载特征来补充:缩小所有特征都被绘制而不考虑可见性,但在缩小时以适当的分辨率绘制。当放大超过一定深度时,使用更详细的特征,但基于边界框进行过滤。
- Canvas
我把它包括在这里只是因为 SVG 有时可能是夹点,这取决于绘制的特征的数量和类型。切换到 Canvas 可以 是改进。
- 投影类型
投影类型确实影响速度,等角投影快,一些方位角投影慢。虽然我只在任何 projection.invert()
,但投影类型是一个因素。
预投影几何是最快的,它完全绕过了投影:特征坐标 space 以像素为单位。有关该主题的更多信息,请参阅
结合边界框方法and/or根据当前范围裁剪的功能,这可能是一种非常快速的方法。
- 缩放事件
我根据你的问题的文字添加:投影功能应该同时放大或不放大。绘图可能是可变的,但投影 运行 是相同的。这表明您可能正在使用 .on("zoom"
事件。这不是很有效:平移事件的每个滴答声都需要重新绘制,换句话说,单个平移可能会触发许多缩放事件。这意味着您需要在平移过程中几乎不断地投射特征。
一个简单的解决方案是使用 .on("end"
事件作为重绘地图的事件。这样我们每次缩放只重绘一次地图。
但是,您可以变得更复杂。如果您希望地图在整个平移事件中跟随鼠标,您可以使用变换来平移地图,避免投影任何东西,然后在缩放结束时,重新投影地图并删除变换。这几乎肯定需要重新考虑您的缩放功能。在确定是否发生平移以避免在缩放比例未更改时重绘群集之前,我采用了某种类似的方法 (example)。