使用d3.js保存并重新加载力布局

前端之家收集整理的这篇文章主要介绍了使用d3.js保存并重新加载力布局前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我试图找到正确的方法,以便能够保存强制图节点布局位置一旦定居,然后再重新加载该布局,并从相同的结算状态重新开始.

我试图通过克隆包含图表的DOM元素,删除它然后重新加载它.

这可以做到,部分如下所示:

_clone = $('#chart').clone(true,true);
$('#chart').remove();

选择包含的div,克隆它并删除它,然后再删除

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,那么您只能正确运行相同的布局过程就像从头开始初始化一样,你会收到保存的图形.

原文链接:https://www.f2er.com/js/152690.html

猜你在找的JavaScript相关文章