【发布时间】:2013-08-14 21:36:26
【问题描述】:
我正在尝试找到正确的方法,以便能够在确定后保存力图节点布局位置,然后重新加载该布局并从相同的已确定状态重新开始。
我试图通过克隆包含图表的 DOM 元素、删除它然后重新加载它来做到这一点。
我可以做到,部分如下所示:-
_clone = $('#chart').clone(true,true);
$('#chart').remove();
选择包含的 div,克隆它并删除它,然后再删除
var _target = $('#p1content');
_target.append(_clone);
选择用于保存图表的div 并重新加载它。重新加载的图表已修复。
我不知道如何重新连接力以允许操纵继续进行。这可能吗?我想保留节点的固定位置。
另一种可能性,我可以重新加载节点位置并以低 alpha 启动力吗?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3: Force layout</title>
<script src="./jquery-2.0.3.min.js" type="text/javascript"></script>
<script type="text/javascript" src="../d3.v3.js"></script>
<style type="text/css">
/* No style rules here yet */
</style>
</head>
<body>
<div data-role="content" id="p1content">
<div id="chart"></div>
</div>
<script type="text/javascript">
//Width and height
var w = 800;
var h = 600;
//Original data
var dataset = {
nodes: [
{ name: "Adam" },
{ name: "Bob" },
{ name: "Carrie" },
{ name: "Donovan" },
{ name: "Edward" },
{ name: "Felicity" },
{ name: "George" },
{ name: "Hannah" },
{ name: "Iris" },
{ name: "Jerry" }
],
edges: [
{ source: 0, target: 1 },
{ source: 0, target: 2 },
{ source: 0, target: 3 },
{ source: 0, target: 4 },
{ source: 1, target: 5 },
{ source: 2, target: 5 },
{ source: 2, target: 5 },
{ source: 3, target: 4 },
{ source: 5, target: 8 },
{ source: 5, target: 9 },
{ source: 6, target: 7 },
{ source: 7, target: 8 },
{ source: 8, target: 9 }
]
};
//Initialize a default force layout, using the nodes and edges in dataset
var force = d3.layout.force()
.nodes(dataset.nodes)
.links(dataset.edges)
.size([w, h])
.linkDistance([100])
.charge([-100])
.start();
var colors = d3.scale.category10();
//Create SVG element
var svg = d3.select("#chart")
.append("svg")
.attr("width", w)
.attr("height", h);
//Create edges as lines
var edges = svg.selectAll("line")
.data(dataset.edges)
.enter()
.append("line")
.style("stroke", "#ccc")
.style("stroke-width", 1);
//Create nodes as circles
var nodes = svg.selectAll("circle")
.data(dataset.nodes)
.enter()
.append("circle")
.attr("r", 10)
.style("fill", function(d, i) {
return colors(i);
})
.call(force.drag);
//Every time the simulation "ticks", this will be called
force.on("tick", function() {
edges.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
nodes.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
});
// After 5 secs clone and remove DOM elements
setTimeout(function() {
_clone = $('#chart').clone(true,true);
$('#chart').remove();
}, 5000);
//After 10 secs reload DOM
setTimeout(function() {
var _target = $('#p1content');
_target.append(_clone);
// WHAT NEEDS TO GO HERE TO RECOUPLE THE FORCE?
}, 10000);
</script>
</body>
</html>
在我放的地方添加了这个 // 什么需要去这里来恢复力量?
这似乎可以拾取已恢复的现有元素并将原力重新耦合到它停止将力节点等传递到超时函数的位置
force = d3.layout.force()
.nodes(dataset.nodes)
.links(dataset.edges)
.size([w, h])
.linkDistance([100])
.charge([-100])
.start();
colors = d3.scale.category10();
//Create SVG element
svg = d3.select("#chart");
//Create edges as lines
edges = svg.selectAll("line")
.data(dataset.edges);
//Create nodes as circles
nodes = svg.selectAll("circle")
.data(dataset.nodes)
.call(force.drag);
//Every time the simulation "ticks", this will be called
force.on("tick", function() {
edges.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
nodes.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
});
【问题讨论】:
-
我不认为你仅仅通过克隆 DOM 元素就能轻易摆脱... 可视化是由 d3.js 内部工作原理创建的,这意味着当你 重新加载,能够再次使用它意味着d3.js 知道它正在处理什么。就是说,如果你复制一个被 d3.jshold 的元素,d3.js 只能处理 original 而不是副本。
-
这意味着您可能必须序列化 d3.js 使用的关于可视化的信息,然后找到一种方法从序列化数据中再次构建它......我不认为这是听起来很简单。
-
是的,我认为这可能并不容易。我当然可以保存数据并重新加载,但是节点的布局不会保留,因为力图可以稳定到一个新位置。这就是查看 DOM 元素以创建快照的原因。但是如果不从头开始有效地重新启动,我无法看到如何将力重新耦合到它
-
我认为除了保存 DOM 元素之外,您还应该考虑保存 d3.js 实际使用的内容。我认为您应该尝试保存 d3.js 正在使用的
nodes和links数组,然后在重新加载脚本时,将其用作计算布局的数据,而不是调用原始数据源。如果您发布您的脚本,我可以尝试更好地解释这一点。 -
添加了示例脚本,谢谢
标签: d3.js force-layout