为什么我不能让D3 Force Directed Graph Link标签工作

时间:2015-07-27 17:28:27

标签: javascript d3.js

我正在尝试将链接标签添加到强制定向图,并支持拖放节点,如此示例here。使用该示例,我能够创建我的图形,并修改了我的要求。

我现在想为链接添加标签。我在这里看到这是一个非常常见的问题,我已经查看了StackOverflow上显示的许多示例,并尝试实现其中的几个。然而,我所看到的那些没有支持拖放节点。我目前正在尝试使用找到的here示例作为模板,并添加了为我的项目创建链接标签的代码,但它仍然不起作用。

以下是我的链接标签代码段:

var vis = d3.select("body").append("svg:svg").attr("width", w).attr("height", h);
var link = vis.selectAll("line.link")
.data(json.links)
.enter().append("svg:line")
.attr("class", "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; })

//****I have added this code to create the link labels****

    vis.append("svg:defs")
    .data(json.links)
    .enter().append("svg:line")
    .attr("id", String)
    .append("svg:path");
var path = vis.append("svg:g").selectAll("path")
.data(force.links())
.enter().append("svg:path")
 .attr("id", function (d) { return d.source.index + "_" +d.target.index; })
.attr("class", function (d) { return "link " + d.linkName; })
.attr("line-end", function (d) { return "url(#" + d.linkName + ")"; });

var path_label = vis.append("svg:g").selectAll(".path_label")
.data(force.links())
.enter().append("svg:text")
.attr("class", "path_label")
.append("svg:textPath")
  .attr("startOffset", "50%")
  .attr("text-anchor", "middle")
  .attr("xlink:href", function (d) { return "#" + d.source.index + "_" + d.target.index; })
  .style("fill", "#000")
  .style("font-family", "Arial")
  .text(function (d) { return d.linkName; });
//****End of added code******

感谢您提供任何帮助或建议。更多信息我添加的代码,如上所示,不会导致图形失败,它会使用节点信息呈现图形,而链接线只是不添加标签。

3 个答案:

答案 0 :(得分:0)

很抱歉没有真正回答您的具体问题,只提供了另一个示例的链接。

Here's我的课程工作,我做了〜1。5年前所以我现在还没有真正记住细节。在github main page上,您可以找到网络编辑器的热键列表(或者只需在控制台中输入Visualizer.test()作为示例)。

此编辑器提供图形节点的选择/添加/删除,拖放等等 - 我认为这就是您所需要的。您可能会觉得有用的编辑器源代码的全部内容都在this file中。

我希望它能以某种方式帮助你:)

答案 1 :(得分:0)

好的,我已经对使用下面显示的代码的代码进行了更改。

var json = {
"nodes": [
    { "name": "Fabby MONDESIR", "dob": "5.24.97", "ImageUrl": "http://172.18.215.101/MugImageAsp/MUGImageASP.ASP?WCI=RetrieveImage&WCE=FD635099", "group": 1 },
    { "name": "ADNES D BRONSON", "dob": "5.24.97", "ImageUrl": "http://172.18.215.101/MugImageAsp/MUGImageASP.ASP?WCI=RetrieveImage&WCE=FD635098", "group": 1 }

],
"links": [
   { "source": 0, "target": 1, "linkName": "test", "value": 8 }

]
}
var w = 1024, h = 768;


var vis = d3.select("body").append("svg:svg").attr("width",   w).attr("height", h);

//Create a force layout and bind Nodes and Links
var force = self.force = d3.layout.force()
.nodes(json.nodes)
.links(json.links)
.gravity(.05)
.distance(250)
.charge(-100)
.size([w, h])
.start();

//draw lines for links between nodes
var link = vis.selectAll("line.link")
.data(json.links)
.enter().append("svg:line")
.attr("class", "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; });


var node_drag = d3.behavior.drag()
.on("dragstart", dragstart)
.on("drag", dragmove)
.on("dragend", dragend);

function dragstart(d, i) {
force.stop() // stops the force auto positioning before you start dragging
}

function dragmove(d, i) {
d.px += d3.event.dx;
d.py += d3.event.dy;
d.x += d3.event.dx;
d.y += d3.event.dy;
tick(); // this is the key to make it work together with updating both px,py,x,y on d !
}

function dragend(d, i) {
d.fixed = true; // of course set the node to fixed so the force doesn't include the node in its auto positioning stuff
tick();
force.resume();
}

//draw the nodes
var node = vis.selectAll("g.node")
.data(json.nodes)
.enter().append("svg:g")
.call(node_drag);
//place photos on the nodes
node.append("svg:image")
.attr("class", "circle")
.attr("class", "circle")
.attr("xlink:href", function (d, i) {
// d is the node data, i is the index of the node
return d.ImageUrl;
})
.attr("x", "-8px")
.attr("y", "-8px")
.attr("width", "96px")
.attr("height", "96px");

//Append text data for the nodes
node.append("svg:text")
.attr("class", "nodetext")
.attr("dx", 0)//offset to move node data off the picture
.attr("dy", -10)
.style("fill", "blue")
.text(function (d) { return d.name });
node.append("svg:text")
    .attr("class", "nodetext")
    .attr("dx", 0)//offset to move node data off the picture
    .attr("dy", 100)
    .style("fill", "blue")
    .text(function (d) { return d.dob });

// Append text to Link lines
var linkText = vis.selectAll(".link")
.data(json.links)
.append("text")
.attr("font-family", "Arial, Helvetica, sans-serif")
.attr("x", function (d) {
if (d.target.x > d.source.x) { return (d.source.x + (d.target.x - d.source.x) / 2); }
else { return (d.target.x + (d.source.x - d.target.x) / 2); }
})
.attr("y", function (d) {
    if (d.target.y > d.source.y) { return (d.source.y + (d.target.y - d.source.y) / 2); }
    else { return (d.target.y + (d.source.y - d.target.y) / 2); }
})
.attr("fill", "Black")
.style("font", "normal 12px Arial")
.attr("dy", ".35em")
.text(function (d) { return d.linkName });


force.on("tick", tick);

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("transform", function (d) { return "translate(" + d.x + "," + d.y + ")"; });

}

正在绘制图形,但仍未将任何文本附加到链接线。当我调试时,我可以看到从图形中拉出x y坐标,并从数据中提取linkName,我只能找出文本没有显示的原因。

答案 2 :(得分:0)

我终于想出了如何让它发挥作用。对于正在寻找支持使用行标签拖放节点的强制定向图

的任何人,工作代码如下所示
var json = {
"nodes": [
{ "name": "Fabby MONDESIR", "dob": "5.24.97","group": 1 },
{ "name": "ADNES D BRONSON", "dob": "5.24.97","group": 1 }

],
"links": [
   { "source": 0, "target": 1, "linkName": "FCC", "value": 8 },
   { "source": 0, "target": 2, "linkName": "Arr", "value": 10 }

]
}
var w = 1024,
h = 768

var vis = d3.select("body").append("svg:svg")
.attr("width", w)
.attr("height", h);

//Create a force layout and bind Nodes and Links
var force = self.force = d3.layout.force()
    .nodes(json.nodes)
    .links(json.links)
    .gravity(.05)
    .distance(250)
    .charge(-100)
    .size([w, h])
    .start();

//draw lines for links between nodes
var link = vis.selectAll(".gLink")
.data(json.links)
          .enter().append("g")
            .attr("class", "gLink")
          .append("line")
            .attr("class", "link")
            .style("stroke", "#ccc")
            .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; });
/*  .data(json.links)
    .enter().append("svg:line")
    .attr("class", "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; });*/


var node_drag = d3.behavior.drag()
    .on("dragstart", dragstart)
    .on("drag", dragmove)
    .on("dragend", dragend);

function dragstart(d, i) {
    force.stop() // stops the force auto positioning before you start dragging
}

function dragmove(d, i) {
    d.px += d3.event.dx;
    d.py += d3.event.dy;
    d.x += d3.event.dx;
    d.y += d3.event.dy;
    tick(); // this is the key to make it work together with updating both px,py,x,y on d !
}

function dragend(d, i) {
    d.fixed = true; // of course set the node to fixed so the force doesn't include the node in its auto positioning stuff
    tick();
    force.resume();
}

//draw the nodes
var node = vis.selectAll("g.node")
    .data(json.nodes)
  .enter().append("svg:g")
    .call(node_drag);
//place mug shots on the nodes
node.append("svg:image")
    .attr("class", "circle")
    .attr("class", "circle")
.attr("xlink:href", function (d, i) {
    // d is the node data, i is the index of the node
    return d.ImageUrl;
})
    .attr("x", "-8px")
    .attr("y", "-8px")
    .attr("width", "96px")
    .attr("height", "96px");

//Append text data for the nodes
node.append("svg:text")
    .attr("class", "nodetext")
    .attr("dx", 0)//offset to move node text off the picture
    .attr("dy", -10)
    .style("fill", "blue")
    .text(function (d) { return d.name });
node.append("svg:text")//this gives us a second text line under the picture
        .attr("class", "nodetext")
        .attr("dx", 0)//offset to move node text off the picture
        .attr("dy", 100)
        .style("fill", "blue")
        .text(function (d) { return d.dob });

// Append text to Link lines
var linkText = vis.selectAll(".gLink")
    .data(json.links)
    .append("text")
    .attr("font-family", "Arial, Helvetica, sans-serif")
    .attr("class", "link")
    .attr("x", function (d) {
        if (d.target.x > d.source.x) { return (d.source.x + (d.target.x - d.source.x) / 2); }
        else { return (d.target.x + (d.source.x - d.target.x) / 2); }
    })
    .attr("y", function (d) {
        if (d.target.y > d.source.y) { return (d.source.y + (d.target.y - d.source.y) / 2); }
        else { return (d.target.y + (d.source.y - d.target.y) / 2); }
    })
    //.attr("fill", "red")
    .style("fill", "Red")
    .style("font", "normal 12px Arial")
   .attr("dy", ".35em")
    .text(function (d) { return d.linkName });


force.on("tick", tick);

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("transform", function (d) { return "translate(" + d.x + "," + d.y + ")"; });

    linkText
      .attr("x", function (d) {
          if (d.target.x > d.source.x) { return (d.source.x + (d.target.x - d.source.x) / 2); }
          else { return (d.target.x + (d.source.x - d.target.x) / 2); }
      })
      .attr("y", function (d) {
          if (d.target.y > d.source.y) { return (d.source.y + (d.target.y - d.source.y) / 2); }
          else { return (d.target.y + (d.source.y - d.target.y) / 2); }
      });
}

由于