我试图通过克隆包含图表的DOM元素,删除它然后重新加载它.
这可以做到,部分如下所示:
_clone = $('#chart').clone(true,true); $('#chart').remove();
var _target = $('#p1content'); _target.append(_clone);
选择用于保存图表的div并重新加载.重装图是固定的.
我不知道如何重新连接力量以允许操纵进行.这可能吗?我想保留节点的安置位置.
另一种可能性,我可以重新加载节点位置,并用低α启动力?
<!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 },target: 3 },target: 4 },{ source: 1,target: 5 },{ source: 2,{ source: 3,{ source: 5,target: 8 },target: 9 },{ source: 6,target: 7 },{ source: 7,{ 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重新连接到超时功能
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! });
现在保存是有价值的,因为x,y坐标(和其他一些东西)已经被添加到每个节点和边缘d3,在布局(但不断变化,直到停止).作为JSON,图形很容易序列化,坚持在localStorage中,再次拉出并解析:
localStorage.setItem(JSON.stringify(graph)); ... localStorage.getItem(JSON.parse('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,那么您只能正确运行相同的布局过程就像从头开始初始化一样,你会收到保存的图形.