首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >强制有向图与局部存储

强制有向图与局部存储
EN

Stack Overflow用户
提问于 2015-12-01 11:36:17
回答 2查看 210关注 0票数 1

我试图在localStorage中拖放后存储节点位置,但是当我重新加载页面时,链接是我保存它们的地方,节点也是,但是链接和节点没有链接,所以节点就离开了它们的初始位置。

这是我的代码,我用的是角。

代码语言:javascript
复制
angular.module('core').controller('HomeController', ['$scope', 
function($scope) {
    $scope.graph = {
        width : 500,
        height : 400,
        color : d3.scale.category20(),
        force : '',
        drag : '',
        dragstart : function(d) {
            d.x = d3.event.x;
            d.y = d3.event.y;
        },
        dragend : function(d) {
            var graphTmp = { "nodes" : $scope.graph.node.data(), "links" : $scope.graph.link.data()};
            localStorage.setItem('graph',JSON.stringify(graphTmp));
        },
        link : [],
        node : [],
        links : [],
        nodes : []
    };
    $scope.svg = d3.select("body").append("svg")
            .attr("width", $scope.graph.width)
            .attr("height", $scope.graph.height);
    $scope.savedGraph = {};

    $scope.draw = function(){
        $scope.graph.force = d3.layout.force()
                .charge(-120)
                .linkDistance(30)
                .size([$scope.graph.width, $scope.graph.height]);

        $scope.graph.force
              .nodes($scope.graph.nodes)
              .links($scope.graph.links)
              .start();

        $scope.graph.link = $scope.svg.selectAll(".link")
            .data($scope.graph.links)
            .enter().append("line")
            .attr("class", "link")
            .style({'stroke' : 'gray', 'stroke-width' : '1px'});

        $scope.graph.drag = $scope.graph.force.drag()
            .on("dragstart", $scope.graph.dragstart)
            .on("dragend", $scope.graph.dragend);

        $scope.graph.node = $scope.svg.selectAll(".node")
            .data($scope.graph.nodes)
            .enter().append("circle")
            .attr("class", "node")
            .attr("r", 5)
            .style("fill", function(d) { return $scope.graph.color(d.group); })
            .call($scope.graph.drag);

        $scope.graph.node
            .append("title")
            .text(function(d) { return d.name; });

        $scope.graph.force.on("tick", function() {
            $scope.graph.link
                .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; });

            $scope.graph.node
                .attr("cx", function(d) { return d.x; })
                .attr("cy", function(d) { return d.y; });
        });
    };

    if(localStorage.getItem('graph') === null){

        $scope.graph.nodes = [
            {"name":"Myriel","group":1},
            {"name":"Napoleon","group":1},
            {"name":"Mlle.Baptistine","group":1},
            {"name":"Mme.Magloire","group":1},
            {"name":"CountessdeLo","group":1},
            {"name":"Geborand","group":1},
            {"name":"Champtercier","group":1},
            {"name":"Cravatte","group":1},
            {"name":"Count","group":1}
        ];

        $scope.graph.links = [
            {"source":1,"target":0,"value":1},
            {"source":2,"target":0,"value":8},
            {"source":3,"target":0,"value":10},
            {"source":3,"target":2,"value":6},
            {"source":4,"target":0,"value":1}
        ];

        $scope.draw();
    }
    else {
        var graphTmp = $.parseJSON(localStorage.getItem('graph'));
        $scope.graph.links = graphTmp.links;
        $scope.graph.nodes = graphTmp.nodes;
        $scope.draw();

    }

有人知道为什么吗?我认为这是因为节点和链接不能仅与node.data()和link.data()数据链接在一起。我可以储存更多的数据吗?

谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-12-01 14:08:42

问题是,最初加载链接(本地存储中没有数据)时,它具有以下结构:

代码语言:javascript
复制
 $scope.graph.links = [{
            "source": 1,
            "target": 0,
            "value": 1
        }, {
            "source": 2,
            "target": 0,
            "value": 8
        }, {
            "source": 3,
            "target": 0,
            "value": 10
        }, {
            "source": 3,
            "target": 2,
            "value": 6
        }, {
            "source": 4,
            "target": 0,
            "value": 1
        }];

现在,强制布局将用节点中的源对象替换源索引。

拖动时,保存节点和链接( links对象将保存源和目标的节点对象)。

现在,当从本地存储加载时,解析链接时,链接源/目标将具有与节点对象不同的对象(因为它的深度克隆)。

因此,节点上的拖动更改将不会反映在链接源/目标object.Hence上,链接将被分离。

解决这个问题的方法是,您总是将链接的索引形式存储在本地存储中。我在这里通过保留另一个对象initLinks来实现这一点。

代码语言:javascript
复制
$scope.graph.nodes = [{
    "name": "Myriel",
    "group": 1
}, {
    "name": "Napoleon",
    "group": 1
}, {
    "name": "Mlle.Baptistine",
    "group": 1
}, {
    "name": "Mme.Magloire",
    "group": 1
}, {
    "name": "CountessdeLo",
    "group": 1
}, {
    "name": "Geborand",
    "group": 1
}, {
    "name": "Champtercier",
    "group": 1
}, {
    "name": "Cravatte",
    "group": 1
}, {
    "name": "Count",
    "group": 1
}];

$scope.graph.links = [{
    "source": 1,
    "target": 0,
    "value": 1
}, {
    "source": 2,
    "target": 0,
    "value": 8
}, {
    "source": 3,
    "target": 0,
    "value": 10
}, {
    "source": 3,
    "target": 2,
    "value": 6
}, {
    "source": 4,
    "target": 0,
    "value": 1
}];
$scope.graph.initLinks = angular.copy($scope.graph.links);

在保存到本地存储时,我会这样做

代码语言:javascript
复制
    var graphTmp = {
        "nodes": $scope.graph.nodes,
        "links": $scope.graph.initLinks
    };

    localStorage.setItem('graph', JSON.stringify(graphTmp));

从本地存储加载时,我会这样做

代码语言:javascript
复制
var graphTmp = JSON.parse(localStorage.getItem('graph'));
$scope.graph.links =  graphTmp.links;
$scope.graph.initLinks = angular.copy(graphTmp.links);
$scope.graph.nodes = graphTmp.nodes;
$scope.draw();

工作代码这里

希望这能有所帮助!

票数 0
EN

Stack Overflow用户

发布于 2017-11-05 20:48:23

如果链接中有复杂的数据,请扩展cyrils答案。您可能希望将对象引用本身替换为它的索引。所有其他数据都被保存下来。注意,在我的应用程序中,我将链接数据单独保存在localstorage中。节点使用另一个密钥保存。

代码语言:javascript
复制
store(key: string, data: any) {
if (key === 'links') {
  // replace all targets and source with indexes, we do not need to serialize the values.
  localStorage.setItem(key, JSON.stringify(data, (k, v) => {
    if (k === 'source' || k === 'target') {
      return v.index;
    } else {
      return v;
    }

  }));

} else {
  localStorage.setItem(key, JSON.stringify(data));
}
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34019473

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档