dc.js - 向散点图添加数据时避免数据点动画
dc.js - avoid data points animation when adding data to scatter plot
我正在尝试使用 dc.js 实现实时数据可视化(即新数据定期到达)。我遇到的问题如下 - 当新数据添加到图中时,已经存在的点通常开始 "dance around",即使它们没有改变。这可以避免吗?
following fiddle 说明了这一点。
我的猜测是 crossfilter 在内部对数据进行排序,这会导致点在图表上移动,因为数据项在内部存储中的位置(索引)发生了变化。数据添加方式如下:
var data = [];
var ndx = crossfilter(data)
setInterval(function() {
var value = ndx.size() + 1;
if (value > 50) {
return;
}
var newElement = {
x: myRandom(),
y: myRandom()
};
ndx.add([newElement]);
dc.redrawAll();
}, 1000);
有什么想法吗?
我支持我上面的评论。 dc.js 应该通过使用键函数绑定数据来修复,处理该问题的最佳方法可能就是使用 .transitionDuration(0)
禁用散点图上的转换
但是,我很好奇是否可以通过使用假组将组保持在固定顺序来解决当前的问题。确实如此,至少对于这个没有聚合的例子,我们只想显示原始数据点。
首先,我们向数据添加第三个字段 index
。这必须按照数据进入的顺序对数据进行排序。正如上面的讨论所述,散点图目前通过其索引绑定数据,因此我们需要将点保持在一个固定的顺序中;什么都不应该插入。
var newElement = {
index: value,
x: myRandom(),
y: myRandom()
};
接下来,我们必须通过分箱和聚合来保留这个索引。我们可以将其保存在键中或值中,但将其保存在键中似乎更合适:
xyiDimension = ndx.dimension(function(d) {
return [+d.x, +d.y, d.index];
}),
xyiGroup = xyiDimension.group();
原来的缩减对我来说没有意义,所以我放弃了。我们将只使用默认行为,即计算落入每个容器的行数。如果包含,计数应为 1,如果过滤掉,则计数应为 0。在密钥中包含索引还可以确保唯一性,而原始密钥不能保证具有唯一性。
现在我们可以创建一个假组,让所有内容按索引排序:
var xyiGroupSorted = {
all: function() {
var ret = xyiGroup.all().slice().sort((a,b) => a.key[2] - b.key[2]);
return ret;
}
}
这将在图表请求时获取原始数据,创建数组的副本(因为原始数据由 crossfilter 所有),并将其排序 return 到正确的顺序。
瞧,我们有一个表现正常的散点图,即使数据已经通过交叉过滤器。
你的 fiddle 分支:https://jsfiddle.net/gordonwoodhull/mj81m42v/13/
[毕竟,也许我们一开始就不应该将数据交给crossfilter!我们本可以创建一个公开原始数据的假组。但也许这种技术有一些用处。至少它证明了几乎总有办法解决 dc.js & crossfilter 中的任何问题。]
我正在尝试使用 dc.js 实现实时数据可视化(即新数据定期到达)。我遇到的问题如下 - 当新数据添加到图中时,已经存在的点通常开始 "dance around",即使它们没有改变。这可以避免吗?
following fiddle 说明了这一点。
我的猜测是 crossfilter 在内部对数据进行排序,这会导致点在图表上移动,因为数据项在内部存储中的位置(索引)发生了变化。数据添加方式如下:
var data = [];
var ndx = crossfilter(data)
setInterval(function() {
var value = ndx.size() + 1;
if (value > 50) {
return;
}
var newElement = {
x: myRandom(),
y: myRandom()
};
ndx.add([newElement]);
dc.redrawAll();
}, 1000);
有什么想法吗?
我支持我上面的评论。 dc.js 应该通过使用键函数绑定数据来修复,处理该问题的最佳方法可能就是使用 .transitionDuration(0)
但是,我很好奇是否可以通过使用假组将组保持在固定顺序来解决当前的问题。确实如此,至少对于这个没有聚合的例子,我们只想显示原始数据点。
首先,我们向数据添加第三个字段 index
。这必须按照数据进入的顺序对数据进行排序。正如上面的讨论所述,散点图目前通过其索引绑定数据,因此我们需要将点保持在一个固定的顺序中;什么都不应该插入。
var newElement = {
index: value,
x: myRandom(),
y: myRandom()
};
接下来,我们必须通过分箱和聚合来保留这个索引。我们可以将其保存在键中或值中,但将其保存在键中似乎更合适:
xyiDimension = ndx.dimension(function(d) {
return [+d.x, +d.y, d.index];
}),
xyiGroup = xyiDimension.group();
原来的缩减对我来说没有意义,所以我放弃了。我们将只使用默认行为,即计算落入每个容器的行数。如果包含,计数应为 1,如果过滤掉,则计数应为 0。在密钥中包含索引还可以确保唯一性,而原始密钥不能保证具有唯一性。
现在我们可以创建一个假组,让所有内容按索引排序:
var xyiGroupSorted = {
all: function() {
var ret = xyiGroup.all().slice().sort((a,b) => a.key[2] - b.key[2]);
return ret;
}
}
这将在图表请求时获取原始数据,创建数组的副本(因为原始数据由 crossfilter 所有),并将其排序 return 到正确的顺序。
瞧,我们有一个表现正常的散点图,即使数据已经通过交叉过滤器。
你的 fiddle 分支:https://jsfiddle.net/gordonwoodhull/mj81m42v/13/
[毕竟,也许我们一开始就不应该将数据交给crossfilter!我们本可以创建一个公开原始数据的假组。但也许这种技术有一些用处。至少它证明了几乎总有办法解决 dc.js & crossfilter 中的任何问题。]