我试图对散点图上的重叠标签做一些事情,就像图片中那样。
我使用d3fc并且它确实很好地定位了标签,但是,即使点数很少(> 100)它也很慢,但实际要求通常是> 1000分。最初构建图表需要很长时间,并且几乎不可能进行缩放/填充。
d3fc有什么问题吗?如果没有,是否有其他稳定的自动标签布局方法可用?
我正在使用贪婪策略:
贪婪策略是一种减少标签重叠的快速方法。它 按顺序添加每个标签,选择标签的位置 与已经添加的矩形重叠最低,并且在内部 容器
fc.layoutGreedy()
这是带有简化可重现代码的jsFiddle(虽然它没有加载d3fs lib) - https://jsfiddle.net/f5oxcyg7/
答案 0 :(得分:1)
代码的问题在于每次呈现图表时都会重新评估布局策略。通常,首次渲染图表时的渲染时间约为100毫秒,但如果需要平滑的平移/缩放,则会出现问题。
我提出的解决方案是“缓存”布局的结果,以便在缩放图表时不重新评估它。但是,当缩放操作完成时,将重新评估布局以消除冲突。
首先,处理缩放事件以打开/关闭缓存行为:
var returnCachedLayout = false;
var zoomBeh = d3.behavior.zoom()
.x(x)
.y(y)
.scaleExtent([0, 500])
.on("zoomstart", function() {
returnCachedLayout = true;
zoom()
})
.on("zoom", zoom)
.on("zoomend", function() {
returnCachedLayout = false;
zoom()
})
然后该策略适用于缓存:
var strategyCache = function (strategy) {
var cachedLayout;
var cache = function(layout) {
if (!returnCachedLayout) {
cachedLayout = strategy(layout);
// determine the offset applied by the layout
for (var i = 0; i< layout.length; i++) {
cachedLayout[i].dx = layout[i].x - cachedLayout[i].x;
cachedLayout[i].dy = layout[i].y - cachedLayout[i].y;
}
} else {
// update the location of each label, including the offset
for (var i = 0; i< layout.length; i++) {
cachedLayout[i].x = layout[i].x - cachedLayout[i].dx;
cachedLayout[i].y = layout[i].y - cachedLayout[i].dy;
}
}
return cachedLayout;
};
return cache;
};
// construct a strategy that uses the "greedy" algorithm for layout, wrapped
// by a strategy that removes overlapping rectangles.
var strategy = strategyCache(fc.layout.strategy.removeOverlaps(fc.layout.strategy.greedy()));
这有点棘手,因为你不能只是从缓存中重新渲染标签,因为缩放行为会导致这些点移动。这就是为什么还存储偏移量,以便可以将其重新应用于新位置的标签。
无论如何,这是一个完整的例子:
https://jsfiddle.net/qrpr0wre/
我希望尽快将其作为d3fc-label-layout的“头等舱”功能。