简体   繁体   English

d3 中具有可折叠属性的强制有向图

[英]force directed graph in d3 with collapsable property

I'm trying to use D3 for a drawing network graph which can show a specific node at first.我正在尝试将 D3 用于绘制网络图,该图可以首先显示特定节点。 Then when clicking on that node, it will expand other nodes.然后当单击该节点时,它将展开其他节点。

I use this code and I have a little changes on that code here, it just shows two of the four nodes.我使用了这段代码,我对这里的代码做了一些改动,它只显示了四个节点中的两个。 I can't figure out why it doesn't show all nodes and why it loses the collapsable property.我无法弄清楚为什么它不显示所有节点以及为什么它会丢失可折叠属性。

 var root; var COLLAPSE_LEVEL = 1; var dataset = { nodes: [ { id: 1708498, name: "Chieh-Jen Wang", w: 88 }, { id: 1710977, name: "jan", w: 88 }, { id: 32944442, name: "mike", w: 88 }, { id: 2761079, name: "ana", w: 88 } ], edges: [ { from: 1708498, to: 1710977, w: 1 }, { from: 1708498, to: 32944442, w: 3 } ] }; var width = 960, height = 1000; var svg = d3 .select("body") .append("svg") .attr("width", width) .attr("height", height); var force = d3.layout .force() .size([width, height]) .on("tick", tick) //gravity(0.2) .linkDistance(height / 13) .charge(function(node) { if (node.type !== "ORG") return -2000; return -30; }); // build the arrow. svg .append("svg:defs") .selectAll("marker") .data(["end"]) // Different link/path types can be defined here .enter() .append("svg:marker") // This section adds in the arrows .attr("id", function(d) { return d; }) .attr("viewBox", "0 -5 10 10") .attr("refX", 12) .attr("refY", 0) .attr("markerWidth", 9) .attr("markerHeight", 5) .attr("orient", "auto") .attr("class", "arrow") .append("svg:path") .attr("d", "M0,-5L10,0L0,5"); var json = dataset; var edges = []; json.edges.forEach(function(e) { var sourceNode = json.nodes.filter(function(n) { return n.id === e.from; })[0], targetNode = json.nodes.filter(function(n) { return n.id === e.to; })[0]; edges.push({ source: sourceNode, target: targetNode, value: e.Value }); }); var username = "Chieh-Jen Wang"; var userid; var othernode = []; for (var i = 0; i < json.nodes.length; i++) { if (json.nodes[i].name === "Chieh-Jen Wang") { userid = json.nodes[i].id; json.nodes[i].collapsing = 0; json.nodes[i].collapsed = false; } else { json.nodes[i].collapsing = 1; json.nodes[i].collapsed = true; othernode.push(json.nodes[i]); } } var link = svg.selectAll(".link"); var node = svg.selectAll(".node"); force.on("tick", function() { // make sure the nodes do not overlap the arrows link.attr("d", function(d) { // Total difference in x and y from source to target diffX = d.target.x - d.source.x; diffY = d.target.y - d.source.y; // Length of path from center of source node to center of target node pathLength = Math.sqrt(diffX * diffX + diffY * diffY); // x and y distances from center to outside edge of target node offsetX = (diffX * d.target.radius) / pathLength; offsetY = (diffY * d.target.radius) / pathLength; return ( "M" + d.source.x + "," + d.source.y + "L" + (d.target.x - offsetX) + "," + (d.target.y - offsetY) ); }); node.attr("transform", function(d) { return "translate(" + dx + "," + dy + ")"; }); }); update(); function update() { var nodes = json.nodes.filter(function(d) { return d.collapsing == 0; }); var links = edges.filter(function(d) { return d.source.collapsing == 0 && d.target.collapsing == 0; }); force .nodes(nodes) .links(links) .start(); link = link.data(links); link.exit().remove(); link .enter() .append("path") .attr("class", "link") .attr("marker-end", "url(#end)"); node = node.data(nodes); node.exit().remove(); node .enter() .append("g") .attr("class", function(d) { return "node " + d.type; }) .attr("id", function(d) { return d.id; }); node .append("circle") .attr("class", "circle") .attr("id", function(d) { return d.id; }) .attr("r", function(d) { d.radius = 10; return d.radius; }) .on("click", function(d) { if (d.id === userid) { for (var i = 0; i < json.nodes.length; i++) { json.nodes[i].collapsing = 0; json.nodes[i].collapsed = false; } } }); // return a radius for path to use //make lable for circles // node.append("text") //.attr("x", 0) // .attr("dy", ".35em") // .attr("text-anchor", "middle") // .attr("class", "text") // .text(function(d) { // return d.name // }); // On node hover, examine the links to see if their // source or target properties match the hovered node. node.on("mouseover", function(d) { link.attr("class", function(l) { if (d === l.source || d === l.target) return "link active"; else return "link inactive"; }); return tooltip.style("visibility", "visible").text(d.name); }); // Set the stroke width back to normal when mouse leaves the node. node .on("mouseout", function() { link.attr("class", "link"); // we hide our tooltip on "mouseout" return tooltip.style("visibility", "hidden"); }) .on("click", click) // we move tooltip during of "mousemove" .on("mousemove", function() { return tooltip .style("top", event.pageY - 30 + "px") .style("left", event.pageX + "px"); }); function click(d) { if (!d3.event.defaultPrevented) { var inc = d.collapsed ? -1 : 1; recurse(d); function recurse(sourceNode) { //check if link is from this node, and if so, collapse edges.forEach(function(l) { if (l.source.id === sourceNode.id) { l.target.collapsing += inc; recurse(l.target); } }); } d.collapsed = !d.collapsed; } update(); } } function tick() { 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; }); node .attr("cx", function(d) { return dx; }) .attr("cy", function(d) { return dy; }); t.attr("x", function(d) { return dx; }).attr("y", function(d) { return dy; }); } var toggleColor = (function() { var currentColor = "black"; return function() { currentColor = currentColor == "black" ? "red" : "black"; d3.select(this).style("fill", currentColor); }; })(); var tooltip = d3 .select("body") .append("div") .attr("class", "tooltip"); var circles = svg.selectAll("circle"); circles.forEach(function(c) {});
 .node { cursor: pointer; font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; font-weight: 300; fill: black; } .node:active { fill: lightgray; } .node .text { fill: white; } .ORG .circle { fill: #1d3649; } .EMR .circle { fill: #b2d0f5; stroke: #5596e6; stroke-dasharray: 3px, 3px; opacity: 0.5; } .EMR .circle:hover { fill: #5596e6; } .link { fill: none; stroke: #eee; stroke-width: 1.5px; font: 10px sans-serif; } .link.active { stroke: darkblue; stroke-width: 4; } .arrow { fill: #666; } .arrow.active { stroke-width: 0 !important; } .tooltip { position: absolute; z-index: 10; visibility: hidden; background-color: lightblue; text-align: center; padding: 4px; border-radius: 4px; font-weight: bold; color: black; } .doubled { fill: red !important; }
 <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> <title>Force-Directed Graph</title> <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> </head> <body> <div id="chart"></div> </body> </html>

Here is a demo with your data and collapsable property这是一个包含您的数据和可折叠属性的演示

 var dataset = { "nodes": [{ "id": 1708498, "name": "Chieh-Jen Wang", "w": 88 }, { "id": 1710977, "name": "jan", "w": 88 }, { "id": 32944442, "name": "mike", "w": 88 },{ "id": 2761079, "name": "ana", "w": 88 }], "edges": [{ "from": 1708498, "to": 1710977, "w": 1 }, { "from": 1708498, "to": 32944442, "w": 3 }] } var width = 960, height = 500; var svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height); var force = d3.layout.force() .size([width, height]) //gravity(0.2) .linkDistance(height / 6) .charge(function(node) { if (node.type !== 'ORG') return -2000; return -30; }); // build the arrow. svg.append("svg:defs").selectAll("marker") .data(["end"]) // Different link/path types can be defined here .enter().append("svg:marker") // This section adds in the arrows .attr("id", function(d) { return d; }) .attr("viewBox", "0 -5 10 10") .attr("refX", 12) .attr("refY", 0) .attr("markerWidth", 9) .attr("markerHeight", 5) .attr("orient", "auto") .attr("class", "arrow") .append("svg:path") .attr("d", "M0,-5L10,0L0,5"); var json = dataset; var edges = []; json.edges.forEach(function(e) { var sourceNode = json.nodes.filter(function(n) { return n.id === e.from; })[0], targetNode = json.nodes.filter(function(n) { return n.id === e.to; })[0]; edges.push({ source: sourceNode, target: targetNode, value: e.Value }); }); for(var i=0; i<json.nodes.length; i++) { json.nodes[i].collapsing = 0; json.nodes[i].collapsed = false; } var link = svg.selectAll(".link"); var node = svg.selectAll(".node"); force.on("tick", function() { // make sure the nodes do not overlap the arrows link.attr("d", function(d) { // Total difference in x and y from source to target diffX = d.target.x - d.source.x; diffY = d.target.y - d.source.y; // Length of path from center of source node to center of target node pathLength = Math.sqrt((diffX * diffX) + (diffY * diffY)); // x and y distances from center to outside edge of target node offsetX = (diffX * d.target.radius) / pathLength; offsetY = (diffY * d.target.radius) / pathLength; return "M" + d.source.x + "," + d.source.y + "L" + (d.target.x - offsetX) + "," + (d.target.y - offsetY); }); node.attr("transform", function(d) { return "translate(" + dx + "," + dy + ")"; }); }); update(); function update(){ var nodes = json.nodes.filter(function(d) { return d.collapsing == 0; }); var links = edges.filter(function(d) { return d.source.collapsing == 0 && d.target.collapsing == 0; }); force .nodes(nodes) .links(links) .start(); link = link.data(links) link.exit().remove(); link.enter().append("path") .attr("class", "link") .attr("marker-end", "url(#end)"); node = node.data(nodes); node.exit().remove(); node.enter().append("g") .attr("class", function(d) { return "node " + d.type }); node.append("circle") .attr("class", "circle") .attr("r", function(d) { d.radius = 30; return d.radius }); // return a radius for path to use node.append("text") .attr("x", 0) .attr("dy", ".35em") .attr("text-anchor", "middle") .attr("class", "text") .text(function(d) { return d.type }); // On node hover, examine the links to see if their // source or target properties match the hovered node. node.on('mouseover', function(d) { link.attr('class', function(l) { if (d === l.source || d === l.target) return "link active"; else return "link inactive"; }); }); // Set the stroke width back to normal when mouse leaves the node. node.on('mouseout', function() { link.attr('class', "link"); }) .on('click', click); function click(d) { if (!d3.event.defaultPrevented) { var inc = d.collapsed ? -1 : 1; recurse(d); function recurse(sourceNode){ //check if link is from this node, and if so, collapse edges.forEach(function(l) { if (l.source.id === sourceNode.id){ l.target.collapsing += inc; recurse(l.target); } }); } d.collapsed = !d.collapsed; } update(); } }
 .node { cursor: pointer; font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; font-weight: 300; fill: black; } .node:active { fill: lightgray; } .node .text { fill: white; } .ORG .circle { fill: #1d3649; } .EMR .circle { fill: #b2d0f5; stroke: #5596e6; stroke-dasharray: 3px, 3px; opacity: 0.5; } .EMR .circle:hover { fill: #5596e6; } .link { fill: none; stroke: #eee; stroke-width: 1.5px; font: 10px sans-serif; } .link.active { stroke: darkblue; stroke-width: 4; } .arrow { fill: #666; } .arrow.active { stroke-width: 0 !important; } .tooltip { position: absolute; z-index: 10; visibility: hidden; background-color: lightblue; text-align: center; padding: 4px; border-radius: 4px; font-weight: bold; color: black; } .doubled { fill: red !important; }
 <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> <title>Force-Directed Graph</title> <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> </head> <body> <div id="chart"></div> </body> </html>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM