在节点单击时从 json 获取数据

Fetching data from json on node click

我使用 D3 和 dagre-d3 创建了下图。

var width = 960, height = 700;

// REMOVE OLD SVG
d3.select("#wkfsvg").remove();
     
// ADD NEW SVG
var graphArea = d3.select("body").append("svg")
   .attr({ width: width, height: height, "pointer-events": "all" })
   .attr("id","wkfsvg");

var g = new dagreD3.graphlib.Graph().setGraph({});

d3.select("svg").
    insert("g", "g");

var nodesJson = [
    {
        
        "nodes": "Initiate",
        "status": "startend",
        "creation_date": "",
        "performer_name": "",
        "execution_type": "Automatic"
    },
    {
       
        "nodes": "Find the Next Approver",
        "status": "completed",
        "creation_date": "",
        "performer_name": "",
        "execution_type": "Automatic"
    },
    {
        
        "nodes": "Check for Manager",
        "status": "completed",
        "creation_date": "",
        "performer_name": "",
        "execution_type": "Automatic"
    },
    {
        "nodes": "Set Status & ACL for IT Project Manager",
        "status": "completed",
        "creation_date": "",
        "performer_name": "",
        "execution_type": "Automatic"
    },
    {
       
        "nodes": "Set Status & ACL for IT Sign Off Approvers",
        "status": "completed",
        "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    },
    {
        
        "nodes": "IT Project Manager Approves",
        "status": "completed",
        "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    },
    {
        "id": "Finance Approver",
        "nodes": "Finance Approver",
        "status": "dormant",
        "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    },
    {
        
        "nodes": "Send Email for Completion",
        "status": "future",
        "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    },
    {
       
        "nodes": "Send to Requestor",
        "status": "future",
        "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    },
    {
        
        "nodes": "Send Email to Requestor",
        "status": "completed",
        "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    },
    {
        "id": "Set ACL on Form for Requestor",
        "nodes": "Set ACL on Form for Requestor",
        "status": "future",
        "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    },
    {
       
        "nodes": "Set Completion ACL on Form",
        "status": "future",
        "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    },
    {
         "id": "Set Completion ACL on PO",
        "nodes": "Set Completion ACL on PO",
        "status": "future",
         "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    },
    {
       
        "nodes": "Set Completion ACL on Attachments",
        "status": "future",
         "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    },
    {
       
        "nodes": "Set ACL on Attachment",
        "status": "completed",
         "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    },
    {
        
        "nodes": "Update Comments of PM Rejection",
        "status": "future",
         "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    },
    {
        
        "nodes": "Update Comments of FA Rejection",
        "status": "future",
         "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    },
    {
        
        "nodes": "Update Comments of PM",
        "status": "completed",
         "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    },
    {
        
        "nodes": "Update Comments of FA",
        "status": "future",
         "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    },
    {
        
        "nodes": "Update Comments of Requestor",
        "status": "future",
         "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    },
    {
       
        "nodes": "End",
        "status": "startend",
         "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    }
];      
 

// Automatically label each of the nodes
nodesJson.forEach(function(node) {
   
    if(node.status == "future") {
        if(node.execution_type == "Manual") {
            g.setNode(node.nodes, { labelType: "html", label: node.nodes+' <tspan dx="0" dy="-10">\uf007</tspan>', class: "future" });            
        } else {
            g.setNode(node.nodes, { label: node.nodes, class: "future" }); 
        }
    } else if(node.status == "completed") {
        if(node.execution_type == "Manual") {
            g.setNode(node.nodes, { labelType: "html", label: node.nodes+' <tspan dx="0" dy="-10">\uf007</tspan>', class: "completed" });
        } else {
            g.setNode(node.nodes, { label: node.nodes, class: "completed" }); 
        }
    } else if(node.status == "dormant") {
       if(node.execution_type == "Manual") {
            g.setNode(node.nodes, { labelType: "html", label: node.nodes, class: "dormant" });
        } else {
            g.setNode(node.nodes, { label: node.nodes, class: "dormant" }); 
        }
    } else if(node.status == "startend") {
        g.setNode(node.nodes, { label: node.nodes, class: "startend" }); 
    } else {
        g.setNode(node.nodes, { label: node.nodes });
    }   
});

var edgesJson = [
    {
 
        "type": "approve",
        "source": "Find the Next Approver",
        "target": "Check for Manager"
    },
    {
        "type": "approve",
        "source": "Check for Manager",
        "target": "Set Status & ACL for IT Sign Off Approvers"
    },
    {
        "type": "approve",
        "source": "Check for Manager",
        "target": "Set Status & ACL for IT Project Manager"
    },
    {
        "type": "approve",
        "source": "Set Status & ACL for IT Project Manager",
        "target": "IT Project Manager Approves"
    },
    {
        "type": "approve",
        "source": "Set Status & ACL for IT Sign Off Approvers",
        "target": "Finance Approver"
    },
    {
        "type": "approve",
        "source": "Set ACL on Form for Requestor",
        "target": "Send to Requestor"
    },
    {
        "type": "approve",
        "source": "Set Completion ACL on Form",
        "target": "Set Completion ACL on PO"
    },
    {
        "type": "approve",
        "source": "IT Project Manager Approves",
        "target": "Send Email to Requestor"
    },
    {
        "type": "approve",
        "source": "Set Completion ACL on PO",
        "target": "Set Completion ACL on Attachments"
    },
    {
        "type": "approve",
        "source": "Set Completion ACL on Attachments",
        "target": "Send Email for Completion"
    },
    {
        "type": "approve",
        "source": "Initiate",
        "target": "Set ACL on Attachment"
    },
    {
        "type": "approve",
        "source": "Set ACL on Attachment",
        "target": "Find the Next Approver"
    },
    {
        "type": "approve",
        "source": "Update Comments of PM Rejection",
        "target": "Set ACL on Form for Requestor"
    },
    {
        "type": "reject",
        "source": "IT Project Manager Approves",
        "target": "Update Comments of PM Rejection"
    },
    {
        "type": "approve",
        "source": "Update Comments of FA Rejection",
        "target": "Set ACL on Form for Requestor"
    },
    {
        "type": "approve",
        "source": "Send Email to Requestor",
        "target": "Update Comments of PM"
    },
    {
        "type": "approve",
        "source": "Update Comments of PM",
        "target": "Set Status & ACL for IT Sign Off Approvers"
    },
    {
        "type": "approve",
        "source": "Finance Approver",
        "target": "Update Comments of FA"
    },
    {
        "type": "approve",
        "source": "Update Comments of FA",
        "target": "Set Completion ACL on Form"
    },
    {
        "type": "reject",
        "source": "Finance Approver",
        "target": "Update Comments of FA Rejection"
    },
    {
        "type": "approve",
        "source": "Send to Requestor",
        "target": "Update Comments of Requestor"
    },
    {
        "type": "approve",
        "source": "Update Comments of Requestor",
        "target": "Check for Manager"
    },
    {
        "type": "approve",
        "source": "Send Email for Completion",
        "target": "End"
    }
]; 

edgesJson.forEach(function(edge) {
    if(edge.type == "approve") {
        g.setEdge(edge.source, edge.target, { label: "" }); 
    }
    // Make the edge of rejected paths red and dashed
   if(edge.type == "reject") {
        g.setEdge(edge.source, edge.target, {
            label: "", class: "rejectEdgePath"
            
        });
    }
});


var svg = d3.select("svg"),
    inner = svg.select("g");

// Set the rankdir
//g.graph().rankdir = "LR";
g.graph().nodesep = 60;

// Set up zoom support
var zoom = d3.behavior.zoom().on("zoom", function() {
      inner.attr("transform", "translate(" + d3.event.translate + ")" +
                                  "scale(" + d3.event.scale + ")");
    });
svg.call(zoom);

// Create the renderer
var render = new dagreD3.render();


// Run the renderer. This is what draws the final graph.
render(inner, g);

// Center the graph
var initialScale = 0.75;
zoom
  .translate([(svg.attr("width") - g.graph().width * initialScale) / 2, 20])
  .scale(initialScale)
  .event(svg);
svg.attr('height', g.graph().height * initialScale + 40);

var selectedNode = inner.selectAll("g.node"); 
selectedNode.on('click', function (d) { 
    console.log('clicked '+d); 
});
.node rect {
  stroke: #333;
  fill: #fff;
}

.edgePath path {
  stroke: #333;
  fill: #333;
  stroke-width: 1.5px;
}

.rejectEdgePath path {
  stroke: red;
  fill: red;
  stroke-width: 1.5px;
  stroke-dasharray: 5, 5;
}



g.dormant > rect { 
  fill: #CC66FF;
}

g.completed > rect { 
  fill: #66FF99;
}

g.future > rect { 
  fill: #99CCFF;
}

g.acquired > rect { 
  fill: #EBBFFF;
}

g.paused > rect { 
  fill: #FF0000;
}

g.startend > rect { 
  fill: #CC6666;
}

foreignobject {
   fill: black;
   font-family: FontAwesome;
   font-size: 15px;
   text-anchor: middle;
//   cursor: move;
}
<link href="http://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet"/>
<script src="http://cpettitt.github.io/project/dagre-d3/latest/dagre-d3.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

单击节点时,我需要查找被单击节点的详细信息。所以我写了下面的代码-

var selectedNode = inner.selectAll("g.node"); selectedNode.on('click', function (d) { console.log('clicked '+d); });

但是,这只是给了我节点名称。我还想打印 nodesJson 的其他属性,例如 'status'、'creation_date'、'performer_name' 等

有人可以建议如何处理吗?

谢谢

我不是 d3.js 方面的专家,所以可能有(好得多)更好的方法来做到这一点。我想到的最简单的方法是查看节点数组,直到找到被单击的节点,然后显示来自该节点的信息。

function getNodeInfo(name) {
    for (var i=0;i<nodesJson.length;i++) 
        if (nodesJson[i].nodes==name) return nodesJson[i]; 
}

最大的问题是,如果您有多个同名节点,它只会获取数组中第一个节点的详细信息。如果这不是问题,那么您可以这样做:

var width = 960, height = 700;

// REMOVE OLD SVG
d3.select("#wkfsvg").remove();
     
// ADD NEW SVG
var graphArea = d3.select("body").append("svg")
   .attr({ width: width, height: height, "pointer-events": "all" })
   .attr("id","wkfsvg");

var g = new dagreD3.graphlib.Graph().setGraph({});

d3.select("svg").
    insert("g", "g");

var nodesJson = [
    {
        
        "nodes": "Initiate",
        "status": "startend",
        "creation_date": "",
        "performer_name": "",
        "execution_type": "Automatic"
    },
    {
       
        "nodes": "Find the Next Approver",
        "status": "completed",
        "creation_date": "",
        "performer_name": "",
        "execution_type": "Automatic"
    },
    {
        
        "nodes": "Check for Manager",
        "status": "completed",
        "creation_date": "",
        "performer_name": "",
        "execution_type": "Automatic"
    },
    {
        "nodes": "Set Status & ACL for IT Project Manager",
        "status": "completed",
        "creation_date": "",
        "performer_name": "",
        "execution_type": "Automatic"
    },
    {
       
        "nodes": "Set Status & ACL for IT Sign Off Approvers",
        "status": "completed",
        "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    },
    {
        
        "nodes": "IT Project Manager Approves",
        "status": "completed",
        "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    },
    {
        "id": "Finance Approver",
        "nodes": "Finance Approver",
        "status": "dormant",
        "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    },
    {
        
        "nodes": "Send Email for Completion",
        "status": "future",
        "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    },
    {
       
        "nodes": "Send to Requestor",
        "status": "future",
        "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    },
    {
        
        "nodes": "Send Email to Requestor",
        "status": "completed",
        "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    },
    {
        "id": "Set ACL on Form for Requestor",
        "nodes": "Set ACL on Form for Requestor",
        "status": "future",
        "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    },
    {
       
        "nodes": "Set Completion ACL on Form",
        "status": "future",
        "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    },
    {
         "id": "Set Completion ACL on PO",
        "nodes": "Set Completion ACL on PO",
        "status": "future",
         "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    },
    {
       
        "nodes": "Set Completion ACL on Attachments",
        "status": "future",
         "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    },
    {
       
        "nodes": "Set ACL on Attachment",
        "status": "completed",
         "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    },
    {
        
        "nodes": "Update Comments of PM Rejection",
        "status": "future",
         "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    },
    {
        
        "nodes": "Update Comments of FA Rejection",
        "status": "future",
         "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    },
    {
        
        "nodes": "Update Comments of PM",
        "status": "completed",
         "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    },
    {
        
        "nodes": "Update Comments of FA",
        "status": "future",
         "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    },
    {
        
        "nodes": "Update Comments of Requestor",
        "status": "future",
         "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    },
    {
       
        "nodes": "End",
        "status": "startend",
         "creation_date": "",
        "performer_name": "",
        "execution_type": "Manual"
    }
];      

function getNodeInfo(name) {
    for (var i=0;i<nodesJson.length;i++) 
        if (nodesJson[i].nodes==name) return nodesJson[i]; 
}
 

// Automatically label each of the nodes
nodesJson.forEach(function(node) {
   
    if(node.status == "future") {
        if(node.execution_type == "Manual") {
            g.setNode(node.nodes, { labelType: "html", label: node.nodes+' <tspan dx="0" dy="-10">\uf007</tspan>', class: "future" });            
        } else {
            g.setNode(node.nodes, { label: node.nodes, class: "future" }); 
        }
    } else if(node.status == "completed") {
        if(node.execution_type == "Manual") {
            g.setNode(node.nodes, { labelType: "html", label: node.nodes+' <tspan dx="0" dy="-10">\uf007</tspan>', class: "completed" });
        } else {
            g.setNode(node.nodes, { label: node.nodes, class: "completed" }); 
        }
    } else if(node.status == "dormant") {
       if(node.execution_type == "Manual") {
            g.setNode(node.nodes, { labelType: "html", label: node.nodes, class: "dormant" });
        } else {
            g.setNode(node.nodes, { label: node.nodes, class: "dormant" }); 
        }
    } else if(node.status == "startend") {
        g.setNode(node.nodes, { label: node.nodes, class: "startend" }); 
    } else {
        g.setNode(node.nodes, { label: node.nodes });
    }   
});

var edgesJson = [
    {
 
        "type": "approve",
        "source": "Find the Next Approver",
        "target": "Check for Manager"
    },
    {
        "type": "approve",
        "source": "Check for Manager",
        "target": "Set Status & ACL for IT Sign Off Approvers"
    },
    {
        "type": "approve",
        "source": "Check for Manager",
        "target": "Set Status & ACL for IT Project Manager"
    },
    {
        "type": "approve",
        "source": "Set Status & ACL for IT Project Manager",
        "target": "IT Project Manager Approves"
    },
    {
        "type": "approve",
        "source": "Set Status & ACL for IT Sign Off Approvers",
        "target": "Finance Approver"
    },
    {
        "type": "approve",
        "source": "Set ACL on Form for Requestor",
        "target": "Send to Requestor"
    },
    {
        "type": "approve",
        "source": "Set Completion ACL on Form",
        "target": "Set Completion ACL on PO"
    },
    {
        "type": "approve",
        "source": "IT Project Manager Approves",
        "target": "Send Email to Requestor"
    },
    {
        "type": "approve",
        "source": "Set Completion ACL on PO",
        "target": "Set Completion ACL on Attachments"
    },
    {
        "type": "approve",
        "source": "Set Completion ACL on Attachments",
        "target": "Send Email for Completion"
    },
    {
        "type": "approve",
        "source": "Initiate",
        "target": "Set ACL on Attachment"
    },
    {
        "type": "approve",
        "source": "Set ACL on Attachment",
        "target": "Find the Next Approver"
    },
    {
        "type": "approve",
        "source": "Update Comments of PM Rejection",
        "target": "Set ACL on Form for Requestor"
    },
    {
        "type": "reject",
        "source": "IT Project Manager Approves",
        "target": "Update Comments of PM Rejection"
    },
    {
        "type": "approve",
        "source": "Update Comments of FA Rejection",
        "target": "Set ACL on Form for Requestor"
    },
    {
        "type": "approve",
        "source": "Send Email to Requestor",
        "target": "Update Comments of PM"
    },
    {
        "type": "approve",
        "source": "Update Comments of PM",
        "target": "Set Status & ACL for IT Sign Off Approvers"
    },
    {
        "type": "approve",
        "source": "Finance Approver",
        "target": "Update Comments of FA"
    },
    {
        "type": "approve",
        "source": "Update Comments of FA",
        "target": "Set Completion ACL on Form"
    },
    {
        "type": "reject",
        "source": "Finance Approver",
        "target": "Update Comments of FA Rejection"
    },
    {
        "type": "approve",
        "source": "Send to Requestor",
        "target": "Update Comments of Requestor"
    },
    {
        "type": "approve",
        "source": "Update Comments of Requestor",
        "target": "Check for Manager"
    },
    {
        "type": "approve",
        "source": "Send Email for Completion",
        "target": "End"
    }
]; 

edgesJson.forEach(function(edge) {
    if(edge.type == "approve") {
        g.setEdge(edge.source, edge.target, { label: "" }); 
    }
    // Make the edge of rejected paths red and dashed
   if(edge.type == "reject") {
        g.setEdge(edge.source, edge.target, {
            label: "", class: "rejectEdgePath"
            
        });
    }
});


var svg = d3.select("svg"),
    inner = svg.select("g");

// Set the rankdir
//g.graph().rankdir = "LR";
g.graph().nodesep = 60;

// Set up zoom support
var zoom = d3.behavior.zoom().on("zoom", function() {
      inner.attr("transform", "translate(" + d3.event.translate + ")" +
                                  "scale(" + d3.event.scale + ")");
    });
svg.call(zoom);

// Create the renderer
var render = new dagreD3.render();


// Run the renderer. This is what draws the final graph.
render(inner, g);

// Center the graph
var initialScale = 0.75;
zoom
  .translate([(svg.attr("width") - g.graph().width * initialScale) / 2, 20])
  .scale(initialScale)
  .event(svg);
svg.attr('height', g.graph().height * initialScale + 40);

var selectedNode = inner.selectAll("g.node"); 
selectedNode.on('click', function (d) { 
    var nodeInfo = getNodeInfo(d);
    console.log('clicked '+nodeInfo.nodes+' (status: '+nodeInfo.status+')'); 
});
.node rect {
  stroke: #333;
  fill: #fff;
}

.edgePath path {
  stroke: #333;
  fill: #333;
  stroke-width: 1.5px;
}

.rejectEdgePath path {
  stroke: red;
  fill: red;
  stroke-width: 1.5px;
  stroke-dasharray: 5, 5;
}



g.dormant > rect { 
  fill: #CC66FF;
}

g.completed > rect { 
  fill: #66FF99;
}

g.future > rect { 
  fill: #99CCFF;
}

g.acquired > rect { 
  fill: #EBBFFF;
}

g.paused > rect { 
  fill: #FF0000;
}

g.startend > rect { 
  fill: #CC6666;
}

foreignobject {
   fill: black;
   font-family: FontAwesome;
   font-size: 15px;
   text-anchor: middle;
//   cursor: move;
}
<link href="http://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet"/>
<script src="http://cpettitt.github.io/project/dagre-d3/latest/dagre-d3.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>