[英]Updating a layout.pack in d3.js
我试图围绕d3的包布局( http://bl.ocks.org/4063530 )。
我有基本的布局工作,但我想用新数据更新它。 即收集新数据,将其绑定到当前layout.pack并相应更新(更新/退出/输入)。
我的尝试在这里( http://jsfiddle.net/emepyc/n4xk8/14/ ):
var bPack = function(vis) {
var pack = d3.layout.pack()
.size([400,400])
.value(function(d) {return d.time});
var node = vis.data([data])
.selectAll("g.node")
.data(pack.nodes)
.enter()
.append("g")
.attr("class", function(d) { return d.children ? "node" : "leaf node"; })
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
node.append("circle")
.attr("r", function(d) { return d.r });
node.filter(function(d) { return !d.children; }).append("text")
.attr("text-anchor", "middle")
.attr("dy", ".3em")
.text(function(d) { return d.analysis_id });
bPack.update = function(new_data) {
console.log("UPDATE");
node
.data([new_data])
.selectAll("g.node")
.data(pack.nodes);
node
.transition()
.duration(1000)
.attr("class", function(d) { return d.children ? "node" : "leaf node" })
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")" });
node.selectAll("circle")
.data(new_data)
.transition()
.duration(1000)
.attr("r", function(d) { return d.r; });
};
具体问题......
如何绑定数据? (因为数据不是复杂的结构而不是数据数组)
如何将新节点/叶子添加到布局中? 旧的删除?
我们将非常感谢对工作范例的指示。
工作范例就在这里 。
基本上,有初始加载的代码,其中所有圆,工具提示等都在初始位置创建和定位。 同样,创建布局(包)。
然后,在按下每个按钮时,将新数据加载到包中,然后重新计算包。 那个关键代码在这里:
在这里你将数据绑定(加载)到包布局:(在我的例子中它的随机数据,当然你将从json或代码或类似的数据):
pack.value(function(d) { return 1 +
Math.floor(Math.random()*501); });
这里计算新布局:
pack.nodes(data);
之后,元素将转换为新位置,并在确定时更改其属性。
我只想强调一点,我不使用enter / update / exit模式或转换(你可能会在其他解决方案中看到),因为我认为这会为这样的例子带来不必要的复杂性。
以下是一些过渡行动的照片:
开始:
过渡:
结束:
我最近遇到了同样的问题,并且也遇到了一般更新模式教程。 这些不符合我的目的。 我在图中有几百个DOM元素(ForceLayout),然后我收到了REST数据,其中包含每个节点的属性。 通过重新绑定数据进行刷新导致重建整个图表,正如您在回应mg1075的建议时所说的那样。 在我的案例中,花了几分钟才完成DOM的更新。
我最终为需要更新的元素分配了唯一的ID,我用JQuery挑选了它们。 我的整个图表设置使用D3,但我的更新没有。 这感觉不好,但它运作得很好。 而不是花费几分钟来销毁和重新创建我的大多数DOM,它需要花费3秒钟的时间(省略REST调用的时间)。 我没有看到在D3中无法实现类似属性更新的原因。
也许如果Mike Bostock在enter()选择中添加了remove()或正确的子选择函数,我们可以按照纯D3模式进行更新。 虽然搞清楚这一点,但我试图绑定一个数据子集,添加新属性的数据,然后进行子选择以获取需要更新的元素,但由于输入的有限和特定性质,它不起作用()选择。
相关的,如果你还没有审查过:
http://bl.ocks.org/3808218 - 一般更新模式,我
http://bl.ocks.org/3808221 - 一般更新模式,II
http://bl.ocks.org/3808234 - 一般更新模式,III
这个样本小提琴没有转换,但这里至少有一种更新数据的方法。
// VISUALIZATION
var svg = d3.select("#kk")
.append("svg")
.attr("width", 500)
.attr("height", 600)
.attr("class", "pack");
var g = svg.append("g")
.attr("transform", "translate(2,2)");
var pack = d3.layout.pack()
.size([400,400])
.value(function(d) {return d.time});
function update(data) {
var nodeStringLenth = d3.selectAll("g.node").toString().length;
if ( nodeStringLenth > 0) {
d3.selectAll("g.node")
.remove();
}
var node = g.data([data]).selectAll("g.node")
.data(pack.nodes);
node.enter()
.append("g")
.attr("class", function(d) { return d.children ? "node" : "leaf node"; })
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
node.append("circle")
.attr("r", function(d) { return d.r });
node.filter(function(d) { return !d.children; }).append("text")
.attr("text-anchor", "middle")
.attr("dy", ".3em")
.text(function(d) { return d.analysis_id });
node
.exit()
.remove();
}
var myData = [data1, data2, data3];
update(data1);
setInterval(function() {
update( myData[Math.floor(Math.random() * myData.length)] ); // http://stackoverflow.com/questions/4550505/getting-random-value-from-an-array?lq=1
}, 1500);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.