d3.js — принудительная компоновка не показывает узлы и ссылки

#d3.js

Вопрос:

Ниже приведен пример, преобразованный из этой версии v3, он пытается использовать принудительный макет для рисования некоторых узлов и ссылок, но он не может отображать узлы или ссылки!

 console.log("--------")
console.clear();
var w = 600,
    h = 600,
    nodeCircles,
    linkLines,
    root;

var force = d3.forceSimulation()
   .force("link", d3.forceLink().id(function(d) { return d.id; }))
   .force("charge", d3.forceManyBody())
   .force("center", d3.forceCenter(w / 2, h / 2))
   .on('tick',tick)

var zoomer = d3.zoom()
.scaleExtent([0.9,3])
.on("zoom", zoom);

function zoom(event) {
  vis.attr("transform", 
           "translate("   event.translate   ")" 
             " scale("   event.scale   ")" );
}

var graph = d3.select("body").append("svg:svg")
.attr("width", w)
.attr("height", h)
.append("g")
.attr("class", "graph")
.call(zoomer);

var rect = graph.append("rect")
.attr("width", w)
.attr("height", h)
.attr('fill','none')
.attr('stroke','black')
.style("pointer-events", "all");  

var vis = graph.append("svg:g")
.attr("class", "plotting-area");

function update() {
  var nodes = d3.hierarchy(root)
  const links = d3.tree()
  .size([h, w])(nodes)
  .links();
  nodes = flatten(root)
  
  force
    .nodes(nodes)
    .on("tick", tick);

  force.force("link")
    .links(links);
  // Update the links…
  linkLines = vis.selectAll("line.link")
    .data(links, function (d) {
    return d.target.index;
  });

  linkLines.enter().insert("svg:line", ".node")
    .attr("class", "link")
  .attr('stroke','black')

  linkLines.exit().remove();

  nodeCircles = vis.selectAll("circle.node")
    .data(nodes, function (d) {
    return d.id;
  })
    .attr("fill", color)
  .attr('stroke','black')

  nodeCircles.enter().append("svg:circle")
    .attr("class", "node")
    .attr("r", function (d) {
       
    return d.children ? 4.5 : Math.sqrt(d.size) / 10;
  })
    .style("fill", color);
  nodeCircles.exit().remove();
}

function color(d) {
  return  d.children ? "#c6dbef" : d.group;
}

function tick() {
  linkLines.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;
  });

  nodeCircles.attr("cx", function (d) {
    return d.x;
  })
    .attr("cy", function (d) {
    return d.y;
  });
}

function readfile(json) {
  root = json;
  root.fixed = true;
  root.x = w / 2;
  root.y = h/2;
  update();
};

function flatten(root) {
  var nodes = [],
      i = 0;

  function recurse(node) {
    if (node.children) node.size = node.children.reduce(function (p, v) {
      return p   recurse(v);
    }, 0);
    if (!node.id) node.id =   i;
    nodes.push(node);
    return node.size;
  }

  root.size = recurse(root);
  return nodes;
}

var data = {
  "dist": 0.00193506541936,
  "name": "N3",
  "children": [ {
    "dist": 0.00488832259274,
    "name": "N4",
    "children": [ {
      "dist": 0.00421186204991,
      "name": "N5",
      "children": [ {
        "dist": 0.0163437491651,
        "name": "N6",
        "children": [{
          "dist": 0.417946674158,
          "group": "blue",
          "name": "CHEMBL1644419",
          "size": 2000.0000000000866
        }, {
          "dist": 0.00543077796308,
          "name": "N8",
          "children": [{
            "dist": 0.0297671023157,
            "name": "N9",
            "children": [{
              "dist": 0.359033872667,
              "group": "red",
              "name": "ASD03540222",
              "size": 2000.0000000000866
            }, {
              "dist": 0.362485114675,
              "group": "red",
              "name": "ASD01150858",
              "size": 2000.0000000000866
            }]
          },{
            "dist": 0.0224504491652,
            "name": "N12",
            "children": [{
              "dist": 0.00178517153851,
              "name": "N13",
              "children": [{
                "dist": 0.364388220986,
                "group": "blue",
                "name": "CHEMBL197161",
                "size": 2000.0000000000866
              }, {
                "dist": 0.0425243314393,
                "name": "N15",
                "children": [{
                  "dist": 0.336193167816,
                  "group": "blue",
                  "name": "CHEMBL1644268",
                  "size": 2000.0000000000866
                }, {
                  "dist": 0.325677335782,
                  "group": "red",
                  "name": "CHEMBL593637",
                  "size": 2000.0000000000866
                }]
              }]
            }, {
              "dist": 0.0246952948163,
              "name": "N18",
              "children": [{
                "dist": 0.358771918732,
                "group": "blue",
                "name": "CHEMBL569878",
                "size": 2000.0000000000866
              }, {
                "dist": 0.36317930078,
                "group": "blue",
                "name": "CHEMBL434267",
                "size": 2000.0000000000866
              }]
            }]
          }]
        }]
      }, {
        "dist": 0.00389420127272,
        "name": "N21",
        "children": [{
          "dist": 0.010842478752,
          "name": "N22",
          "children": [{
            "dist": 0.415105380276,
            "group": "blue",
            "name": "CHEMBL1275732",
            "size": 2000.0000000000866
          }, {
            "dist": 0.0337121910412,
            "name": "N24",
            "children": [{
              "dist": 0.0664262587727,
              "name": "N25",
              "children": [{
                "dist": 0.315587114957,
                "group": "red",
                "name": "ASD00170175",
                "size": 2000.0000000000866
              }, {
                "dist": 0.310918909139,
                "group": "red",
                "name": "CHEMBL292368",
                "size": 2000.0000000000866
              }]
            }, {
              "dist": 0.376684365543,
              "group": "red",
              "name": "ASD00170052",
              "size": 2000.0000000000866
            }]
          }]
        }, {
          "dist": 0.00704072756384,
          "name": "N29",
          "children": [{
            "dist": 0.0103358142929,
            "name": "N30",
            "children": [{
              "dist": 0.412662682696,
              "group": "blue",
              "name": "CHEMBL14370",
              "size": 2000.0000000000866
            }, {
              "dist": 0.427337317304,
              "group": "blue",
              "name": "CHEMBL94700",
              "size": 2000.0000000000866
            }]
          }, {
            "dist": 0.0142382687979,
            "name": "N33",
            "children": [{
              "dist": 0.403816741996,
              "group": "blue",
              "name": "CHEMBL545557",
              "size": 2000.0000000000866
            }, {
              "dist": 0.0752386947609,
              "name": "N35",
              "children": [{
                "dist": 0.316746014667,
                "group": "blue",
                "name": "CHEMBL506342",
                "size": 2000.0000000000866
              }, {
                "dist": 0.314832932701,
                "group": "red",
                "name": "CHEMBL1256402",
                "size": 2000.0000000000866
              }]
            }]
          }]
        }]
      } ]
    }]
  } ] };

readfile(data) 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script> 

Комментарии:

1. Просто быстро, выбор неизменяем (на данный момент не могу найти хорошую ссылку на вопрос/ответ) — vis.selectAll("circle.node") возвращает пустой выбор, поэтому nodeCircles он пуст, и функция галочки ничего не обновляет, вам нужно будет переопределить его (и выбор ссылок) или сделать новый выбор, например: nodeCircles = nodeCircles.enter().append("svg:circle").merge(nodeCircles)... . Это должно помочь (у вас также должен быть атрибут ширины штриха для ссылок), хотя я замечаю, что есть и другие проблемы, которые могут потребовать более пристального внимания, чем у меня есть на данный момент.

2. 1. Исправьте выбор (как указал @AndrewReid) 2. В tick() , заменить d.source.x на d.source.data.x (то же самое с d.цель)