Рендеринг связей между узлами в D3 (Force Directed Graphs)

Я работаю над следующим примером Робина Фришмана.

До сих пор мне удавалось отображать узлы в браузере, и все, кажется, идет гладко, но я не могу отобразить реляционные ссылки.

Я вижу элементы группировки (для узлов, текста и ссылок) в элементах dev tools, но, похоже, я не могу получить ссылки для соединения узлов, а также чтобы узлы не сходились друг с другом правильно...

Код ниже (некоторая помощь будет наиболее ценится!)

HTML:

<head>
  <meta charset='utf-8'>
  <title>User Interaction (FDG)</title>
  <script src='https://d3js.org/d3.v4.js'></script>
</head>

<body>
  <script src='../js/user-interaction.js'></script>
</body>

JS:

// Data:
const nodes = [
  { id: "mammal", group: 0, label: "Mammals", level: 1 },
  { id: "dog"   , group: 0, label: "Dogs"   , level: 2 },
  { id: "cat"   , group: 0, label: "Cats"   , level: 2 },
  { id: "fox"   , group: 0, label: "Foxes"  , level: 2 },
  { id: "elk"   , group: 0, label: "Elk"    , level: 2 },
  { id: "insect", group: 1, label: "Insects", level: 1 },
  { id: "ant"   , group: 1, label: "Ants"   , level: 2 },
  { id: "bee"   , group: 1, label: "Bees"   , level: 2 },
  { id: "fish"  , group: 2, label: "Fish"   , level: 1 },
  { id: "carp"  , group: 2, label: "Carp"   , level: 2 },
  { id: "pike"  , group: 2, label: "Pikes"  , level: 2 }
];

const links = [
    { target: "mammal", source: "dog" , strength: 0.7 },
    { target: "mammal", source: "cat" , strength: 0.7 },
  { target: "mammal", source: "fox" , strength: 0.7 },
  { target: "mammal", source: "elk" , strength: 0.7 },
  { target: "insect", source: "ant" , strength: 0.7 },
  { target: "insect", source: "bee" , strength: 0.7 },
  { target: "fish"  , source: "carp", strength: 0.7 },
  { target: "fish"  , source: "pike", strength: 0.7 },
  { target: "cat"   , source: "elk" , strength: 0.1 },
  { target: "carp"  , source: "ant" , strength: 0.1 },
  { target: "elk"   , source: "bee" , strength: 0.1 },
  { target: "dog"   , source: "cat" , strength: 0.1 },
  { target: "fox"   , source: "ant" , strength: 0.1 },
    { target: "pike"  , source: "cat" , strength: 0.1 }
];

const getNodeColor = (node) => {
  return node.level === 1 ? 'red' : 'blue';
}

const width = 700,
      height = 600;

const svg = d3.select('body').append('svg')
  .attr('width', width)
  .attr('height', height);

const nodeElements = svg.append('g')
  .attr('class', 'nodes')
  .selectAll('circle')
  .data(nodes)
  .enter().append('circle')
    .attr('r', 10)
    .attr('fill', getNodeColor);

const textElements = svg.append('g')
  .attr('class', 'texts')
  .selectAll('text')
  .data(nodes)
  .enter().append('text')
    .text((nodes) => {return nodes.label;})
    .attr('font-size', 15)
    .attr('dx', -10)
    .attr('dy', 25);

const linkElements = svg.append('g')
  .attr('class', 'links')
  .selectAll('line')
  .data(links)
  .enter().append('line')
    .attr('stroke-width', 1.5)
    .attr('stroke', 'rgba(50, 50, 50, 0.2)');

const linkForce = d3.forceLink()
  .id((link) => {return link.id;})
  .strength((link) => {return link.strength;});

const simulation = d3.forceSimulation()
  .force('link', linkForce)
  .force('charge', d3.forceManyBody().strength(-50))
  .force('center', d3.forceCenter(width/2, height/2));

simulation.nodes(nodes).on('tick', () => {
  nodeElements
    .attr('cx', (nodes) => {return nodes.x;})
    .attr('cy', (nodes) => {return nodes.y;})
  textElements
    .attr('x', (nodes) => {return nodes.x;})
    .attr('y', (nodes) => {return nodes.y;})
  linkElements
    .attr('x1', (link) => {return link.source.x;})
    .attr('y1', (link) => {return link.source.y;})
    .attr('x2', (link) => {return link.target.x;})
    .attr('y2', (link) => {return link.target.y;})
});

0 ответов

Другие вопросы по тегам