D3v4: missing text in circle for force directed graph [duplicate]

会有一股神秘感。 提交于 2019-12-02 13:13:40

问题


I am working on a simple visualisation with d3 to draw a force directed graph. I developed from the code at https://bl.ocks.org/mbostock/ad70335eeef6d167bc36fd3c04378048 and I have also added a marker. However, I am struggling to draw a text under each node. The code is as follows:

var nodes_url = "https://api.myjson.com/bins/1dedy1";
var edges_url = "https://api.myjson.com/bins/74lzt";
var marker = d3.select("svg").append('defs')
 .append('marker')
 .attr("id", "Triangle")
 .attr("refX", 12)
 .attr("refY", 6)
 .attr("markerUnits", 'userSpaceOnUse')
 .attr("markerWidth", 12)
 .attr("markerHeight", 18)
 .attr("orient", 'auto')
 .append('path')
 .attr("d", 'M 0 0 12 6 0 12 3 6');

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

var color = d3.scaleOrdinal(d3.schemeCategory20);

var simulation = d3.forceSimulation()
 .force("link", d3.forceLink().id(function(d) { return d.id; }))
 .force("charge", d3.forceManyBody())
 .force("center", d3.forceCenter(width / 2, height / 2));

queue()
 .defer(d3.json, nodes_url)
 .defer(d3.json, edges_url)
 .await(function(error, file1, file2) {createForceLayout(file1, file2);   
});

function createForceLayout (nodes, links) {

 var link = svg.append("g")
 .attr("class", "links")
 .selectAll("line")
 .data(links)
 .enter().append("line")
 .style("stroke", "black")
 .style("opacity", .5)
 .style("stroke-width", "2px");

var node = svg.append("g")
 .attr("class", "nodes")
 .selectAll("circle")
 .data(nodes)
 .enter()
 .append("g")
 .attr("class", "node")
 .append("circle")
 .attr("r", 5)
 .style("fill", "lightgray")
 .style("stroke", "black")
 .style("stroke-width", "1px")
 .call(d3.drag()
 .on("start", dragstarted)
 .on("drag", dragged)
 .on("end", dragended));

node.append("title")
 .text(function(d) { return d.id; });

node.append("text")
 .style("text-anchor", "middle")
 .attr("y", 15)
 .text(function(d) {return d.id});

d3.selectAll("line").attr("marker-end", "url(#Triangle)");

simulation
  .nodes(nodes)
  .on("tick", ticked);

 simulation.force("link")
   .links(links);

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

function dragstarted(d) {
  if (!d3.event.active) simulation.alphaTarget(0.3).restart();
  d.fx = d.x;
  d.fy = d.y;
}

function dragged(d) {
  d.fx = d3.event.x;
  d.fy = d3.event.y;
}

function dragended(d) {
  if (!d3.event.active) simulation.alphaTarget(0);
  d.fx = null;
  d.fy = null;
}

The output returns the text, however, it is not displayed. Any thoughts on what can I be doing wrong?

Thanks a lot!


回答1:


Right now, node is an "enter" selection for the circles, and you cannot append text to circles.

Solution: break the node selection, and change the ticked function accordingly:

var node = svg.append("g")
    .attr("class", "nodes")
    .selectAll("gregorMendel")
    .data(nodes)
    .enter()
    .append("g")
    .attr("class", "node");

var circles = node.append("circle")
    .attr("r", 5)
    .style("fill", "lightgray")
    .style("stroke", "black")
    .style("stroke-width", "1px")
    .call(d3.drag()
        .on("start", dragstarted)
        .on("drag", dragged)
        .on("end", dragended));

var titles = node.append("title")
    .text(function(d) {
        return d.id;
    });

var text = node.append("text")
    .style("text-anchor", "middle")
    .attr("y", 15)
    .text(function(d) {
        return d.id
    });

Here is the demo:

var nodes_url = "https://api.myjson.com/bins/1dedy1";
var edges_url = "https://api.myjson.com/bins/74lzt";
var marker = d3.select("svg").append('defs')
  .append('marker')
  .attr("id", "Triangle")
  .attr("refX", 12)
  .attr("refY", 6)
  .attr("markerUnits", 'userSpaceOnUse')
  .attr("markerWidth", 12)
  .attr("markerHeight", 18)
  .attr("orient", 'auto')
  .append('path')
  .attr("d", 'M 0 0 12 6 0 12 3 6');

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

var color = d3.scaleOrdinal(d3.schemeCategory20);

var simulation = d3.forceSimulation()
  .force("link", d3.forceLink().id(function(d) {
    return d.id;
  }))
  .force("charge", d3.forceManyBody())
  .force("center", d3.forceCenter(width / 2, height / 2));

d3.queue()
  .defer(d3.json, nodes_url)
  .defer(d3.json, edges_url)
  .await(function(error, file1, file2) {
    createForceLayout(file1, file2);
  });

function createForceLayout(nodes, links) {

  var link = svg.append("g")
    .attr("class", "links")
    .selectAll("line")
    .data(links)
    .enter().append("line")
    .style("stroke", "black")
    .style("opacity", .5)
    .style("stroke-width", "2px");

  var node = svg.append("g")
    .attr("class", "nodes")
    .selectAll("gregorMendel")
    .data(nodes)
    .enter()
    .append("g")
    .attr("class", "node");

  var circles = node.append("circle")
    .attr("r", 5)
    .style("fill", "lightgray")
    .style("stroke", "black")
    .style("stroke-width", "1px")
    .call(d3.drag()
      .on("start", dragstarted)
      .on("drag", dragged)
      .on("end", dragended));

  var titles = node.append("title")
    .text(function(d) {
      return d.id;
    });

  var text = node.append("text")
    .style("text-anchor", "middle")
    .attr("y", 15)
    .text(function(d) {
      return d.id
    });

  d3.selectAll("line").attr("marker-end", "url(#Triangle)");

  simulation
    .nodes(nodes)
    .on("tick", ticked);

  simulation.force("link")
    .links(links);

  function ticked() {
    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 + ")";
    })
  }
}

function dragstarted(d) {
  if (!d3.event.active) simulation.alphaTarget(0.3).restart();
  d.fx = d.x;
  d.fy = d.y;
}

function dragged(d) {
  d.fx = d3.event.x;
  d.fy = d3.event.y;
}

function dragended(d) {
  if (!d3.event.active) simulation.alphaTarget(0);
  d.fx = null;
  d.fy = null;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="300" height="200"></svg>


来源:https://stackoverflow.com/questions/43986482/d3v4-missing-text-in-circle-for-force-directed-graph

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!