尽管在开始看到明显的减速(取决于大小、渐变填充的使用等)之前您只能渲染约 2-5k SVG 元素,但您可以在客户端存储和操作更大的数据集。您通常可以在 SVG 中有效地处理数万或数十万个数据点:诀窍是对您实际渲染的内容非常有选择性,并仅在必要时使用去抖动等技术重绘。
(对于非常大的数据集:是的,您需要聚合/子采样点或预渲染。)
考虑到这一点,我特别用于 d3 地图的一种技术是d3.geom.quadtree()
在用户平移/缩放时动态剔除点。更具体地说,我避免绘制点
- 在当前地图边界框之外(因为它们根本不可见),或者
- 太靠近其他点(因为这些点会增加视觉混乱并且无论如何都很难与之交互)。
在 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.)
}