12

我正在使用传单和 d3 创建地图。地图上会绘制很多圆圈。在浏览器兼容性方面,浏览器可以呈现多少 svg 元素存在预期限制。然而,就用户体验而言,我希望用户可以在地图上看到尽可能多的元素(否则用户可能需要不断地放大和缩小,并且需要等待 ajax 返回数据)。我需要考虑一些优化(用户等待时间用户与服务器查询负载与浏览器可以处理的内容)。

看情节,现在服务器返回的点数有限制,因此只有一部分地图被填充。

在此处输入图像描述

浏览器无法在此处处理完全填充的地图,并且用户还需要等待太长时间才能获得服务器响应。

我想我面临的问题需要通过回答两个问题来解决:

  • 就地图上简单 svg 形状(圆形)的数量而言,普通浏览器可以处理什么方面是否有标准?
  • 在地图上显示尽可能多的形状的最佳技术是什么?

我正在考虑以下几点,但我不确定它是否会有所帮助;

  • 使用正方形而不是圆形
  • 使用传单 API 而不是 D3
4

5 回答 5

6

笼统地说,您正在考虑的任何一点都无济于事。在这两种情况下,浏览器要完成的处理量/要显示的信息量将大致相同。

关于你的第一个问题,我不知道。浏览器和平台之间存在巨大差异(特别是如果您也考虑移动设备),平均几乎没有意义。此外,这种情况还在不断变化。我发现多达 1000 个简单的形状通常不是问题。

为了在地图上显示尽可能多的形状,我会将它们预渲染为位图图块,然后使用传单 API 或 d3.geo.tile 之类的东西(此处为示例)将其覆盖在实际地图上。通过这种方式,您可以轻松扩展到数百万个点。

于 2013-09-09T17:06:47.607 回答
5

尽管在开始看到明显的减速(取决于大小、渐变填充的使用等)之前您只能渲染约 2-5k SVG 元素,但您可以在客户端存储和操作更大的数据集。您通常可以在 SVG 中有效地处理数万或数十万个数据点:诀窍是对您实际渲染的内容非常有选择性,并仅在必要时使用去抖动等技术重绘

(对于非常大的数据集:是的,您需要聚合/子采样点或预渲染。)

考虑到这一点,我特别用于 d3 地图的一种技术是d3.geom.quadtree()在用户平移/缩放时动态剔除点。更具体地说,我避免绘制点

  1. 在当前地图边界框之外(因为它们根本不可见),或者
  2. 太靠近其他点(因为这些点会增加视觉混乱并且无论如何都很难与之交互)。

在 JS-ish 伪代码中,这看起来大致如下:

function getIndicesToDraw(data, r, bbox) {
  var indicesToDraw = [];
  var Q = d3.geom.quadtree();
  // set bounds in pixel space
  for (var i = 0; i < data.length; i++) {
    var d = data[i];
    var p = getPointForDatum(d);
    if (isInsideBoundingBox(bbox, p) && !hasPointWithinRadius(Q, r, p)) {
      Q.add(p); 
      indicesToDraw.push(i);
    }
  }
  return indicesToDraw;
}

function redraw(svg, data, r, bbox) {
  var indicesToDraw = getIndicesToDraw(data, r, bbox);
  var points = svg.selectAll('.data-point')
    .data(indicesToDraw, function(i) { return i; });

  // draw new points for points.enter()

  points.exit().remove();

  // update positions of points (or SVG transforms, etc.)
}
于 2016-04-04T18:44:44.877 回答
4

这是一个制图问题,也是一个技术问题。仅仅因为您可以在地图上放置数千个点并不意味着您应该这样做。您应该问问自己,您的用户是否需要一次查看尽可能多的点,并因此更好地理解数据。看到这么多点会让用户感到困惑和不知所措,还是会帮助他们完成他们想要的任务?有什么方法可以过滤数据,以便不需要一次绘制所有点?

这个问题最常见的解决方案是使用集群,通常使用类似Leaflet MarkerCluster的东西。过去,在使用 D3 和 Leaflet 时,我通过创建任意网格、将每个点分配给 bin 并将色带应用于网格来创建一种热图。但是,回到您最初的关注点,它的计算量相当大。

根据您要支持的平台,请注意手机和平板电脑并不总是能很好地处理 SVG,尤其是在绘制数千个特征时。

潜在性能提升的另一个地方是点几何的交付。我不确定您当前是如何加载它们的,但是使用空间索引的 PostGIS 表并通过边界框进行选择通常很快,但是因为您绘制的是点而不是多边形,您甚至可以将它们加载到浏览器中通过 CSV,它比 GeoJSON 或 Topojson 小得多。

于 2013-09-18T01:15:09.403 回答
1

我会一次加载所有数据,但只在视口中绘制足够大的圆圈。在缩放或平移时,删除不应显示的圆圈并检查是否应添加以前隐藏的圆圈。

于 2013-09-09T16:20:49.563 回答
0

您可以使用 canvas + three.js 或 webgl,其中可以加入另一个地图和 10k 动画创建的 3d 模型或原生代码 svg 一些元素,以及一个场景中的交互式实时动画非常好。我已经测试了这个方法的乐趣。对不起,我的英语不好。另一种说法——我认为可能使用了 dlsl 着色器、opengl+ wasm 等等

于 2021-09-30T01:54:40.663 回答