gpt4 book ai didi

d3.js - 使用 d3.js 保存和重新加载强制布局

转载 作者:行者123 更新时间:2023-12-03 20:56:52 25 4
gpt4 key购买 nike

我试图找到正确的方法,以便能够在稳定后保存力图节点布局位置,然后重新加载该布局并从相同的稳定状态重新开始。

我试图通过克隆包含图表的 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; });

});

最佳答案

编辑:现在完整的解决方案!
此外,这种方法将适用于各种场景——既可以在单个页面上停止和重新启动布局,也可以在不同页面上保存和重新加载布局。
首先,在布局过程结束时保存原始 JSON 图,您可以使用以下命令进行监听:

force.on('tick', function(){
...
}).on('end', function(){
// Run this when the layout has finished!
});
现在保存很有值(value),因为在布局期间,d3 已将 x、y 坐标(和其他一些东西)添加到每个节点和边(但要不断更改,直到停止)。作为 JSON,该图很容易序列化,粘贴在 localStorage 中,拉出并再次解析:
localStorage.setItem(JSON.stringify(graph));
...
JSON.parse(localStorage.getItem('graph'));
但是,一旦您将其从存储中取出,您不仅需要一个 JSON 对象,您还想将该保存的对象重新转换为 svg,并且理想情况下,为了简单起见,使用 d3.layout.force 中已有的设备。事实上,你可以这样做—— 有一些小的变化 .
如果您将保存的图形重新粘贴回来,即只需运行
force
.nodes(graph.nodes)
.links(graph.links)
.start();
使用保存的图表,你会得到两个奇怪的行为。
奇怪的行为 1 和解决方案
基于 good documentation , 在起始图中包含 x 和 y 坐标会覆盖布局过程的随机初始化——但只是初始化。所以你会得到节点应该在的地方,但是随着布局的变化,它们会漂浮到一个均匀分布的圆圈中。为了防止这种情况发生,请使用:
  for(n in graph.nodes){
graph.nodes[n].fixed = 1
}
运行前 force.start() .
怪异行为 2 和解决方案
现在你的节点和边都会在你想要的地方,但是你的边会——缩小?
发生了类似的事情,但不幸的是,您不能使用完全相同的解决方案。边长保存在 JSON 对象中,并用于布局的初始化,但随后布局对它们施加了默认长度 (20),除非您首先将边长保存在 JSON 图中——
.on('end', function() {

links = svg.selectAll(".link")[0]
for(i in graph.links){
graph.links[i].length = links[i].getAttribute('length')
}
localStorage.setItem('graph', JSON.stringify(graph));

});
然后,在 force.start() 之前——
force.linkDistance(function (d) { return d.length })
(其文档可以在 here 中找到),最后,您的图表将看起来像它应该的样子。
总之,如果您确保您的 JSON 图 1) 在节点上具有 x,y 坐标,2) 将节点设置为 fixed=1 , 和 3) force.start() 之前设置了 linkDistance ,然后您可以像从头开始初始化一样运行完全相同的布局过程,然后您将恢复保存的图形。

关于d3.js - 使用 d3.js 保存和重新加载强制布局,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18206231/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com