在节点单击时从 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>
我使用 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>