【问题标题】:Drawing a radial tree from node and edges rather than children从节点和边而不是子节点绘制径向树
【发布时间】:2014-12-16 21:41:23
【问题描述】:

我能够从 neo4j 数据中使用 d3 绘制图表,但我在绘制树时遇到了困难。我见过的示例使用了一个 json 文件,其中每个节点都包含一个由其自己的子节点组成的数组。虽然这看起来很方便,但与 neo4j 交互并不容易——至少对我来说是这样。事实上,neo4j 不允许从 (n)--(m) 图中返回 {nodes: collect(distinct {name: n.name, children: collect(distinct {name: m.name})})}。然而,它会让人们从路径中返回节点和边的集合。

我的问题,是否可以在 d3 中从节点和边绘制一棵树,而数据结构中的每个节点都没有子节点?

非常感谢提前 皮埃尔

【问题讨论】:

    标签: d3.js tree neo4j


    【解决方案1】:

    从 neo4j 中检索节点和关系的密码查询将是:

    MATCH p=() <-[:REPORTS8TO]- ()
    UNWIND nodes(p) AS n UNWIND rels(p) AS r 
    WITH n, r ORDER BY n.Name 
    RETURN {nodes: COLLECT(DISTINCT n), links: COLLECT(DISTINCT {source: id(endNode(r)), target: id(startNode(r))})}
    

    因此,javascript 和 d3 代码: - 从 json 中提取节点和关系

    var obj = JSON.parse(xmlhttp.responseText);
    var json = obj.data[0][0];
    
    var nodeMap = {};
    json.nodes.forEach(function(x) {
        nodeMap[x.id] = x;
        nodeMap[x.id].children = [];
    });
    
    var links = json.links.map(function(x) {
        nodeMap[x.source].children.push(nodeMap[x.target]);
        return { source: nodeMap[x.source], target: nodeMap[x.target] };
    });
    

    画树

    d3.select("#tree").select("svg").remove();
    
    var width = 280, height = 870;
    
    var margin = {
            top: 0,
            bottom: 0,
            left: 10,
            right: 120
        }
    
    var tree = d3.layout.tree()
        .size([height - margin.top - margin.bottom, width - margin.left - margin.right]);
    
    var diagonal = d3.svg.diagonal()
        .projection(function(d) { return [d.y, d.x]; });
    
    var vis = d3.select("#tree").append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom )
        .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
    
    // Compute the new tree layout from root
    var nodes = tree.nodes(root).reverse(), links = tree.links(nodes);
    
    var link = vis.selectAll("path.link")
        .data(links)
        .enter().append("path")
        .attr("class", "link")
        .attr("d", diagonal);
    
    var node = vis.selectAll("g.node")
        .data(nodes)
        .enter().append("g")
        .attr("class", "node")
        .attr("transform", function(d) { return "translate(" + d.y + ", " + d.x + ")"; })
    
    node.append("rect")
        .attr("width", 9)
        .attr("height", 9)
        .attr("y", -4)
        .attr("class", function(d) { return "node "+d.type; } );
    
    node.append("text")
        .attr("dx", function(d) { return d.children ? -14 : 14; })
        .attr("dy", 4)
        .attr("text-anchor", function(d) { return d.children ? "end" : "start"; })
        .attr("class", function(d) {return "node "+d.type+" text"; })
        .attr("style", "stroke-wdth: 0.5px; font: 10px sans-serif;")
        .text(function(d) { if (d.Name != "Panel") { return d.Name; }});
    

    【讨论】:

      【解决方案2】:

      对于返回经理和他们各自的孩子的密码查询怎么样。

      match (manager)<-[:REPORTS_TO]-(direct_reports)
      return id(manager), collect(id(direct_reports))
      

      【讨论】:

      • 确实,这很有效,并且类似于我描述的密码查询。根据 d3 tree.js 示例,我需要同时拥有节点列表及其子节点,以及边列表。通过您的查询,我可以报告节点及其子节点的列表,但如果我对边执行相同的操作,在同一个查询中避免遍历图形两次,它会失败:match (:Panel {Name: "Panel"})
      • 当你说edge 我想你是指关系belongsTo 但你实际上是指孩子的孩子或孙子。这是一个公平的说法吗?
      • 该图从一棵树开始,其中包含一组肿瘤和与之相关的细胞系。我将关系命名为 belongsTo。每个肿瘤都连接到一个名为 panel 的根节点。我尝试做的是使用 d3 径向树显示该树,因此我的查询从根节点开始,并为每个节点返回其子节点以及所有关系标记为 json 格式的边。
      • D3 示例读取包含最终附加到根的嵌套节点的 json 文件,因为我不能 - 不知道如何 - 从单个密码查询生成该文件,我尝试报告单个节点及其子节点的级别以及直接从节点和链接构建树的关系(链接)。一定有更简单的方法,但我没有找到任何从 json 文件开始的示例。
      猜你喜欢
      • 2021-08-15
      • 1970-01-01
      • 2012-10-03
      • 1970-01-01
      • 1970-01-01
      • 2016-05-23
      • 1970-01-01
      • 2015-03-20
      • 1970-01-01
      相关资源
      最近更新 更多