繁体   English   中英

D3JS 力网络:链接到使用变换 fnt 中的公式分组的节点

[英]D3JS Force network: Links to nodes that are grouped using formula in transform fnt

我正在将公式应用于 D3js 强制网络图中的集群节点。 我不知道如何让我的链接附加到新的集群节点位置。

对于节点,我从以下位置更改了原始代码:

force.on("tick", function() {
      node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });

要按类别 (nodeCategory) 对节点进行编码,请执行以下操作:

node.attr("transform", function(d) {
  var xm = d.x + intensity*Math.cos(angle*nodeGroup(d.nodeCategory));
  var ym = d.y + intensity*Math.sin(angle*nodeGroup(d.nodeCategory));
  return "translate(" + xm + "," + ym + ")";
});

节点现在根据它们在数据中的类别成功集群。 但是,我不知道如何更新链接(边)的代码。 链接不再附加到节点并反映非集群节点位置:

edges.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; });

如何将转换应用于链接? 任何帮助将不胜感激!

编辑:这是一个说明问题的jsfiddle

蒂姆

问题在于链接位于错误的位置,因为节点通过分组变换从它们的 (dx,dy) 位置移位。 所以d.source.xd.source.y不是你想要的链接位置。

您需要更新 dx 和 dy 以反映节点的真实位置,以便链接位于您想要的位置。

通常的方法是这样的......

force.on("tick", function(e) {

    node.attr("transform", function(d) {
      d.x += (intensity*Math.cos(angle*nodeGroup(d.nodeCategory)) - d.x)*e.alpha;
      d.y += (intensity*Math.sin(angle*nodeGroup(d.nodeCategory)) - d.y)*e.alpha;
      return "translate(" + d.x + "," + d.y + ")";
    });
    edges.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; });
}

这个想法是有一个位置调节器,其增益是α力的函数。 这样,节点移动的速度会随时间衰减。

这是在上下文中......

 //Width and height for SVG area var w = 500; var h = 200; // nb_group, angle, intensity: Used in clustering the nodes var nb_group=4; var angle = 2*Math.PI/nb_group; var intensity = 100; var svg = d3.select("body").append("svg") .attr("width", w) .attr("height", h) var colors = d3.scale.category10() .range(["#FFFF00", //YELLOW "#377eb8", //BLUE "#4daf4a", //GREEN "#e41a1c", //RED ]); var dataset = { "nodes":[ {"id":0,"name":"A","nodeCategory":"1"}, {"id":1,"name":"AA","nodeCategory":"1"}, {"id":2,"name":"B","nodeCategory":"2"}, {"id":3,"name":"BB","nodeCategory":"2"}, {"id":4,"name":"C","nodeCategory":"3"}, {"id":5,"name":"CC","nodeCategory":"3"}, {"id":6,"name":"D","nodeCategory":"4"}, {"id":7,"name":"DD","nodeCategory":"4"}, {"id":8,"name":"DDD","nodeCategory":"4"} ], "edges":[ {"source":0,"target":2,"value":""}, {"source":1,"target":3,"value":""}, {"source":2,"target":4,"value":""}, {"source":3,"target":5,"value":""}, {"source":4,"target":6,"value":""}, {"source":5,"target":7,"value":""}, {"source":6,"target":8,"value":""}, {"source":7,"target":0,"value":""}, {"source":8,"target":1,"value":""} ] } var force = d3.layout.force() .nodes(dataset.nodes) .links(dataset.edges) .gravity(.5) .charge(-100) .linkDistance(10) .size([w, h]) .start(); var drag = force.drag() .on("dragstart", dragstart); var edges = svg.selectAll("line") .data(dataset.edges) .enter() .append("line") .style("stroke", "black"); var nodes = svg.selectAll("g.node") .data(dataset.nodes) .enter() .append("g") .on("dblclick", dblclick) .call(drag); nodes.append("circle") .attr("r", 10) .style("fill", function(d) { return colors(d.nodeCategory); }) .style("stroke", "black") // Mousover Node - highlight node by fading the node colour during mouseover .on('mouseover', function(d){ var nodeSelection = d3.select(this).style({opacity:'0.5'}); }) //Mouseout Node - bring node back to full colour .on('mouseout', function(d){ var nodeSelection= d3.select(this).style({opacity:'1.0',}) }) // dx sets how close to the node the label appears nodes.append("text") .attr("class", "nodetext") .attr("dx", 12) .attr("dy", ".35em") .text(function(d) { return d.name }); // Just the name // Edge Paths var edgepaths = svg.selectAll(".edgepath") .data(dataset.edges) .enter() .append('path') .attr({'d': function(d) {return 'M '+d.source.x+' '+d.source.y+' L '+ d.target.x +' '+d.target.y}, 'id':function(d,i) {return 'edgepath'+i}}) .style("pointer-events", "none"); force.on("tick", function(e) { // position regulator for nodes must update dx and dy BEFORE links are positioned nodes.attr("transform", function(d) { dx += (intensity*Math.cos(angle*(d.nodeCategory)) + w/2 - dx)*e.alpha; dy += (intensity*Math.sin(angle*(d.nodeCategory)) + h/2 - dy)*e.alpha; return "translate(" + dx + "," + dy + ")"; }); edges.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; }); // ORIGINAL transform for Nodes: // nodes.attr("transform", function(d) { return "translate(" + dx + "," + dy + ")"; }); // New Transform for nodes: // PROBLEM HERE edgepaths.attr('d', function(d) { var path='M '+d.source.x+' '+d.source.y+' L '+ d.target.x +' '+d.target.y; //console.log(d) return path}); }); // Double click to 'unfix' the node and have forces start to act on it again. function dblclick(d) { d3.select(this).classed("fixed", d.fixed = false); } // Set the "fixed" property of the dragged node to TRUE when a dragstart event is initiated, // - removes "forces" from acting on that node and changing its position. function dragstart(d) { d3.select(this).classed("fixed", d.fixed = true); }
 body { margin: 0; } svg { outline: 1px solid red; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

暂无
暂无

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

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