javascript - 无法为d3js强制布局网络可视化添加标签

标签 javascript python json d3.js force-layout

我一直在努力尝试使用 d3js 在力导向布局网络可视化中实现标签(我使用 Python 和 Flask 从 API 生成 JSON 文件并在网页中呈现可视化。

我看过很多例子,比如...

http://bl.ocks.org/mbostock/2706022

http://bl.ocks.org/mbostock/1153292

http://bl.ocks.org/MoritzStefaner/1377729

...但我是 Javascript 的新手,所以我很难将这些代码片段重新实现到我当前的代码中:

我一直使用的 JSON 文件是:

{"directed": true, "graph": [], "nodes": [{"id": "user1"}, {"id": "user2"}, {"id": "user3"}, {"id": "user4"}, {"id": "user5"}, {"id": "user6"}, {"id": "user7"}, {"id": "user8"}, {"id": "user9"}, {"id": "user10"}, {"id": "user11"}, {"id": "user12"}, {"id": "user13"}, {"id": "user14"}, {"id": "user15"}, {"id": "user16"}, {"id": "user17"}, {"id": "user18"}, {"id": "user19"}, {"id": "user20"}, {"id": "user21"}, {"id": "user22"}, {"id": "myaccount"}, {"id": "user23"}, {"id": "user24"}, {"id": "user25"}, {"id": "user26"}, {"id": "user27"}, {"id": "user28"}, {"id": "user29"}, {"id": "user30"}, {"id": "user31"}, {"id": "user32"}, {"id": "user33"}, {"id": "user34"}, {"id": "user35"}, {"id": "user36"}, {"id": "user37"}, {"id": "user38"}, {"id": "user39"}, {"id": "user40"}, {"id": "user41"}, {"id": "user42"}, {"id": "user43"}, {"id": "user44"}, {"id": "user45"}, {"id": "user46"}, {"id": "user47"}, {"id": "user48"}, {"id": "user49"}, {"id": "user50"}, {"id": "user51"}, {"id": "user52"}, {"id": "user53"}, {"id": "user54"}, {"id": "user55"}, {"id": "user56"}, {"id": "user57"}, {"id": "user58"}, {"id": "user59"}, {"id": "user60"}, {"id": "user61"}, {"id": "user62"}, {"id": "user63"}, {"id": "user64"}, {"id": "user65"}, {"id": "user66"}, {"id": "user67"}, {"id": "user68"}, {"id": "user69"}, {"id": "user70"}, {"id": "user71"}, {"id": "user72"}, {"id": "user73"}, {"id": "user74"}, {"id": "user75"}, {"id": "user76"}, {"id": "user77"}, {"id": "user78"}, {"id": "user79"}, {"id": "user80"}, {"id": "user81"}, {"id": "user82"}, {"id": "user83"}, {"id": "user84"}, {"id": "user85"}, {"id": "user86"}, {"id": "user87"}, {"id": "user88"}, {"id": "user89"}, {"id": "user90"}, {"id": "user91"}, {"id": "user92"}, {"id": "user93"}, {"id": "user94"}, {"id": "user95"}, {"id": "user96"}, {"id": "user97"}, {"id": "user98"}, {"id": "user99"}, {"id": "user100"}, {"id": "user101"}, {"id": "user102"}, {"id": "cuser103"}, {"id": "user104"}, {"id": "user105"}, {"id": "user106"}, {"id": "user107"}, {"id": "user108"}, {"id": "user109"}, {"id": "user110"}, {"id": "user111"}, {"id": "user112"}, {"id": "user113"}, {"id": "user114"}, {"id": "user115"}, {"id": "user116"}, {"id": "user117"}, {"id": "user118"}, {"id": "user119"}, {"id": "user120"}, {"id": "user121"}, {"id": "user122"}, {"id": "user123"}, {"id": "user124"}, {"id": "user125"}, {"id": "user126"}, {"id": "user127"}, {"id": "user128"}, {"id": "user129"}, {"id": "user130"}, {"id": "user131"}], "links": [{"source": 22, "target": 72, "weight": 1}, {"source": 22, "target": 65, "weight": 3}, {"source": 22, "target": 115, "weight": 1}, {"source": 22, "target": 56, "weight": 1}, {"source": 22, "target": 106, "weight": 1}, {"source": 22, "target": 124, "weight": 3}, {"source": 22, "target": 48, "weight": 1}, {"source": 22, "target": 101, "weight": 1}, {"source": 22, "target": 111, "weight": 1}, {"source": 22, "target": 64, "weight": 4}, {"source": 22, "target": 112, "weight": 1}, {"source": 22, "target": 71, "weight": 1}, {"source": 48, "target": 121, "weight": 1}, {"source": 48, "target": 114, "weight": 1}, {"source": 48, "target": 34, "weight": 1}, {"source": 48, "target": 28, "weight": 1}, {"source": 48, "target": 43, "weight": 1}, {"source": 48, "target": 52, "weight": 1}, {"source": 48, "target": 64, "weight": 1}, {"source": 56, "target": 101, "weight": 1}, {"source": 56, "target": 9, "weight": 1}, {"source": 56, "target": 50, "weight": 1}, {"source": 56, "target": 85, "weight": 1}, {"source": 64, "target": 51, "weight": 1}, {"source": 64, "target": 46, "weight": 1}, {"source": 64, "target": 104, "weight": 1}, {"source": 64, "target": 122, "weight": 1}, {"source": 64, "target": 20, "weight": 2}, {"source": 64, "target": 2, "weight": 1}, {"source": 64, "target": 23, "weight": 1}, {"source": 64, "target": 94, "weight": 1}, {"source": 64, "target": 60, "weight": 1}, {"source": 64, "target": 6, "weight": 1}, {"source": 64, "target": 89, "weight": 1}, {"source": 64, "target": 96, "weight": 1}, {"source": 64, "target": 131, "weight": 3}, {"source": 64, "target": 50, "weight": 1}, {"source": 65, "target": 73, "weight": 2}, {"source": 65, "target": 90, "weight": 1}, {"source": 65, "target": 11, "weight": 3}, {"source": 65, "target": 1, "weight": 3}, {"source": 65, "target": 29, "weight": 4}, {"source": 65, "target": 13, "weight": 1}, {"source": 65, "target": 83, "weight": 1}, {"source": 65, "target": 78, "weight": 1}, {"source": 65, "target": 88, "weight": 1}, {"source": 65, "target": 113, "weight": 2}, {"source": 65, "target": 63, "weight": 1}, {"source": 71, "target": 10, "weight": 1}, {"source": 72, "target": 98, "weight": 3}, {"source": 72, "target": 123, "weight": 1}, {"source": 72, "target": 91, "weight": 1}, {"source": 72, "target": 12, "weight": 1}, {"source": 72, "target": 107, "weight": 1}, {"source": 72, "target": 7, "weight": 2}, {"source": 72, "target": 36, "weight": 4}, {"source": 72, "target": 128, "weight": 4}, {"source": 72, "target": 129, "weight": 1}, {"source": 72, "target": 38, "weight": 2}, {"source": 101, "target": 69, "weight": 1}, {"source": 101, "target": 119, "weight": 1}, {"source": 101, "target": 82, "weight": 1}, {"source": 101, "target": 21, "weight": 1}, {"source": 101, "target": 116, "weight": 1}, {"source": 101, "target": 125, "weight": 1}, {"source": 101, "target": 4, "weight": 1}, {"source": 101, "target": 109, "weight": 1}, {"source": 101, "target": 64, "weight": 2}, {"source": 101, "target": 53, "weight": 1}, {"source": 101, "target": 130, "weight": 1}, {"source": 101, "target": 102, "weight": 1}, {"source": 101, "target": 32, "weight": 1}, {"source": 101, "target": 80, "weight": 1}, {"source": 101, "target": 62, "weight": 1}, {"source": 106, "target": 103, "weight": 1}, {"source": 106, "target": 84, "weight": 1}, {"source": 106, "target": 66, "weight": 1}, {"source": 106, "target": 67, "weight": 1}, {"source": 106, "target": 87, "weight": 1}, {"source": 106, "target": 15, "weight": 1}, {"source": 106, "target": 126, "weight": 2}, {"source": 106, "target": 74, "weight": 1}, {"source": 106, "target": 127, "weight": 1}, {"source": 106, "target": 42, "weight": 4}, {"source": 106, "target": 5, "weight": 1}, {"source": 106, "target": 77, "weight": 2}, {"source": 106, "target": 79, "weight": 1}, {"source": 106, "target": 118, "weight": 1}, {"source": 111, "target": 92, "weight": 1}, {"source": 111, "target": 54, "weight": 1}, {"source": 111, "target": 55, "weight": 1}, {"source": 111, "target": 95, "weight": 1}, {"source": 111, "target": 41, "weight": 2}, {"source": 111, "target": 3, "weight": 1}, {"source": 111, "target": 93, "weight": 3}, {"source": 111, "target": 76, "weight": 1}, {"source": 111, "target": 49, "weight": 1}, {"source": 111, "target": 99, "weight": 1}, {"source": 111, "target": 44, "weight": 1}, {"source": 111, "target": 61, "weight": 1}, {"source": 111, "target": 117, "weight": 2}, {"source": 111, "target": 81, "weight": 1}, {"source": 111, "target": 97, "weight": 1}, {"source": 112, "target": 26, "weight": 1}, {"source": 112, "target": 8, "weight": 1}, {"source": 112, "target": 39, "weight": 1}, {"source": 112, "target": 45, "weight": 1}, {"source": 112, "target": 57, "weight": 1}, {"source": 112, "target": 47, "weight": 1}, {"source": 112, "target": 108, "weight": 1}, {"source": 112, "target": 37, "weight": 5}, {"source": 112, "target": 17, "weight": 1}, {"source": 112, "target": 31, "weight": 1}, {"source": 112, "target": 131, "weight": 4}, {"source": 112, "target": 94, "weight": 1}, {"source": 115, "target": 18, "weight": 3}, {"source": 115, "target": 19, "weight": 1}, {"source": 115, "target": 33, "weight": 1}, {"source": 115, "target": 30, "weight": 1}, {"source": 115, "target": 110, "weight": 1}, {"source": 115, "target": 70, "weight": 1}, {"source": 124, "target": 120, "weight": 1}, {"source": 124, "target": 0, "weight": 1}, {"source": 124, "target": 40, "weight": 1}, {"source": 124, "target": 105, "weight": 1}, {"source": 124, "target": 35, "weight": 1}, {"source": 124, "target": 27, "weight": 1}, {"source": 124, "target": 86, "weight": 3}, {"source": 124, "target": 68, "weight": 1}, {"source": 124, "target": 14, "weight": 1}, {"source": 124, "target": 58, "weight": 1}, {"source": 124, "target": 24, "weight": 1}, {"source": 124, "target": 25, "weight": 1}, {"source": 124, "target": 100, "weight": 1}, {"source": 124, "target": 59, "weight": 1}, {"source": 124, "target": 75, "weight": 2}, {"source": 124, "target": 16, "weight": 2}], "multigraph": false}

目前生成无标签可视化的代码是:

var width = 600,
    height = 500;

var color = d3.scale.category20();

var force = d3.layout.force()
    .charge(-120)
    .linkDistance(30)
    .size([width, height]);

var svg = d3.select("div").append("svg")
    .attr("width", width)
    .attr("height", height);

d3.json("static/reblognetwork_{{ session_username }}.json", function(error, graph) {
  force
      .nodes(graph.nodes)
      .links(graph.links)
      .start();

  var link = svg.selectAll(".link")
      .data(graph.links)
    .enter().append("line")
      .attr("class", "link")
      .style("stroke-width", function(d) { return Math.sqrt(d.value); });

  var node = svg.selectAll(".node")
      .data(graph.nodes)
    .enter().append("circle")
      .attr("class", "node")
      .attr("r", 5)
      .style("fill", function(d) { return color(d.group); })
      .call(force.drag);

  node.append("text")
    // .attr("x", 12)
    // .attr("dy", ".35em")
    .text(function(d) { return d.id; });

  // var text = svg.append("g").selectAll("text")
  //   .data(graph.nodes)
  // .enter().append("text")
  //   // .attr("x", ".5em")
  //   // .attr("y", ".31em")
  //   .text(function(d) { return d.id; });

  force.on("tick", function() {
    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; });

  });
});

你也可以看到我尝试过但没有成功的一些(注释掉的)代码,基于之前的问题,比如 D3.js, force-graph, cannot display text/label of nodes

感谢任何帮助!


解决方案:下面的最终代码有效。

<script src="http://d3js.org/d3.v3.min.js"></script>

<script>
var width = 500, height = 450;

var svg = d3.select("div").append("svg");

var color = d3.scale.category20();

var force = d3.layout.force()
    .charge(-120)
    .linkDistance(30)
    .size([width, height]);

svg.attr("width", width)
    .attr("height", height);

d3.json("static/reblognetwork_{{ session_username }}.json", function(error, graph) {
  force
      .nodes(graph.nodes)
      .links(graph.links)
      .start();

  var link = svg.selectAll(".link")
      .data(graph.links)
    .enter().append("line")
      .attr("class", "link")
      .style("stroke-width", function(d) { return Math.sqrt(d.value); });

  var node = svg.selectAll("g.node")
      .data(graph.nodes);
  var nodeEnter = node.enter()
      .append("g")
      .attr("class", "node")
      .call(force.drag);
  nodeEnter.append("circle")
      .attr("r", 5)
      .style("fill", function(d) { return color(d.group); })
      .call(force.drag);

  nodeEnter.append("text")
     .attr("dx", 5)
     .style("text-anchor", "start")
     .text(function(d) { return d.id; });

  force.on("tick", function() {
    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] + ")";
    });
  });
};


</script>

<div id="networkgraph"></div>

最佳答案

我不擅长故障排除,但我将您的代码插入 JSFiddle,并且节点似乎呈现(虽然不是链接)。

也许这与您传递的数据有关?在这种情况下,我插入了 Les Miserables 数据以对其进行测试(因此我所做的唯一更改是剥离 d3.json 调用并缩小节点文本的大小)。

http://jsfiddle.net/JA4kD/1/

var width = 500,
    height = 450;

var svg = d3.select("#networkgraph").append("svg");

var color = d3.scale.category20();

var force = d3.layout.force()
    .charge(-120)
    .linkDistance(30)
    .size([width, height]);

svg.attr("width", width)
    .attr("height", height);

force.nodes(graph.nodes)
    .links(graph.links)
    .start();

var link = svg.selectAll(".link")
    .data(graph.links)
  .enter().append("line")
    .attr("class", "link")
    .style("stroke-width", function (d) { return Math.sqrt(d.value); });

var node = svg.selectAll("g.node")
    .data(graph.nodes);

var nodeEnter = node.enter()
    .append("g")
    .attr("class", "node")
    .call(force.drag);

nodeEnter.append("circle")
    .attr("r", 5)
    .style("fill", function (d) { return color(d.group); })
    .call(force.drag);

nodeEnter.append("text")
    .attr("dx", 5)
    .style("text-anchor", "start")
    .style("font-size", "8px")
    .text(function (d) { return d.name; });

force.on("tick", function () {
    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] + ")"; });
});

关于javascript - 无法为d3js强制布局网络可视化添加标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23638888/

相关文章:

javascript - 查找不带扩展名的图像的 MIME 类型

python - 将变量传递到 WTForms 类

python - 查找最高键

android - 如何使用 Kotlin 从 android 中的 Assets 中读取 json 文件?

javascript - 拖放排序不适用于动态元素

javascript - 突出显示窗体边框不起作用

javascript - 获取给定 Angular x 和 y 增量值

Python Bokeh : How do I keep the y-axis tick marks stable?

php - echo json 数据然后 sleep

Java 访问 JSON 字符串中的数据