D3.js - 单击节点后无法设置节点标签?

D3.js - Cannot set node labels after node click?

我采用了 http://jsbin.com/omokap/8/edit?html,css,js,output 的想法,在 D3.js 中实现了一个简单的网络可视化应用程序。

此应用程序从html页面的文本区域读取节点名称(以换行符分隔),然后构建一个所有节点相互连接的网络。

我所有的代码都包含在这封邮件的末尾。

我的问题是无法为节点设置标签。
更具体地说,我在网络浏览器上加载 D3jNetVis.html 时收到以下错误消息。

Uncaught TypeError: D3jNetVis.js:64
undefined is not a function

当我尝试在以下代码片段中为节点设置标签时发生此错误:

dataSet.nodes.append("text")
    .attr("x", 12)
    .attr("dy", ".35em")
    .text(function(d) { return d.name; });

这种类型的节点标签 setter 在 D3.js, force-graph, cannot display text/label of nodes 中被建议。

我为什么会收到此错误以及如何修复它有什么想法吗?

Google 提示这可能与 html 页面中 js 文件的导入顺序有关,但一直在尝试各种组合但没有成功。

谢谢,
埃尔诺·林德福斯

D3jNetVis.html:

<!DOCTYPE html>
<html>
    <head>
        <meta charset=utf-8 />
        <title>Network Visualization Example - d3js</title>
        <link rel="stylesheet" type="text/css" href="D3jNetVis.css">
    </head>
    <body>
        <table>
            <tr><td><div id="svgContent"></div></td></tr>
            <tr><th align="left">Give node ids</th></tr>
            <tr><td><textarea id="nodeIds" cols=5 rows=20></textarea></td></tr>
            <tr><td><button type="button" onclick="constNet()">Construct Network</button></td></tr>
        </table>
        <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
        <script src="D3jNetVis.js" charset="utf-8"></script>
    </body>
</html>

D3jNetVis.js:

function constNet() {
    var textArea = document.getElementById("nodeIds");
    var nodeIdsArray = document.getElementById("nodeIds").value.split("\n");
    var w = 500,
    h = 500;
    var svg = d3.select("#svgContent")
        .append("svg")
        .attr("width", w)
        .attr("height", h)
        .attr('preserveAspectRatio', 'xMinYMin slice') 
        .append('g');

    var nodesArray = [];
    for (var i = 0; i < nodeIdsArray.length; i++) {
        var nodeId = nodeIdsArray[i];
        var newNode = {name: "Node" + nodeId, id:nodeId, fixed:false};
        nodesArray[nodesArray.length] = newNode;
    }
    var edgesArray = [];
    for (var i = 0; i < nodeIdsArray.length-1; i++) {
        var sNodeId = nodeIdsArray[i];
        for (var j = i+1; j < nodeIdsArray.length; j++) {
            var tNodeId = nodeIdsArray[j];
            edgesArray[edgesArray.length] = {source:sNodeId-1, target:tNodeId-1}; 
        }
    }
    var dataSet = {
        nodes: nodesArray,
        edges: edgesArray
    };
    var force = self.force = d3.layout.force()
        .nodes(dataSet.nodes)
        .links(dataSet.edges)
        .gravity(0.05)
        .distance(100)
        .charge(-100)
        .size([w,h])
        .start();

    var link = svg.selectAll(".link")
        .data(dataSet.edges)
        .enter().append("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);

    var node = svg.selectAll("circle")
        .data(dataSet.nodes)
        .enter().append("circle")
        .attr("class", "node")
        .attr("r", 4.5)
        .call(node_drag);

    /*
    The "Uncaught TypeError" happens in the next line.
     */
    dataSet.nodes.append("text")
        .attr("x", 12)
        .attr("dy", ".35em")
        .text(function(d) { return d.name; });


    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(); 
    }

    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();
    }  
    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("cx", function(d) { return d.x; })
            .attr("cy", function(d) { return d.y; });
    }
}

D3jNetVis.css:

line{
    stroke: #cccccc;
    stroke-width: 1;
}
circle{
  fill: blue;
}

您可以将 html 元素附加到选择的 html 元素中(这样浏览器就知道在 DOM 中附加的位置)。

dataSet.nodes 不是 html 元素的选择,这就是您收到错误消息的原因。

改写: node.append("text").....