Рисование ссылок, которые не влияют на физику силового ориентированного графа.

1

Мне нужно нарисовать некоторые ссылки между узлами в силовом графе, но я хотел бы, чтобы эти ссылки не влияли на физику графика. Существуют и другие существующие ссылки, которые влияют на физику.

В прилагаемом примере я хотел бы нарисовать ссылки, определенные как "links2", но попросить их просто "следить" за компоновкой остальной части графика. Я бы хотел, чтобы эти линии были анимированы как часть симуляции, но не влияли на окончательный график.

Я вручную нарисовал то, что хотел бы, чтобы конечный результат выглядел.

Изображение 174551

Я не знаю, как отдельно ссылаться на узлы, которые являются частью макета силы.

  var nodes = [
    { name: "node0" },
    { name: "node1" },
    { name: "node2" },
    { name: "node3" },
    { name: "node4" },
    { name: "node5" },
    { name: "node6" },
    { name: "node7" },
    { name: "node8" },
    { name: "node9" },
    { name: "node10" },
    { name: "node11" },
    { name: "node12" },
    { name: "node13" },
    { name: "node14" },
    { name: "node15" },
    { name: "node16" },
    { name: "node17" },
    { name: "node18" },
    { name: "node19" }
  ];

  var links = [
    { source: 0, target: 9 },
    { source: 1, target: 9 },
    { source: 2, target: 9 },
    { source: 3, target: 9 },
    { source: 4, target: 9 },
    { source: 5, target: 9 },
    { source: 6, target: 9 },
    { source: 7, target: 9 },
    { source: 8, target: 9 },
    { source: 10, target: 19 },
    { source: 11, target: 19 },
    { source: 12, target: 19 },
    { source: 13, target: 19 },
    { source: 14, target: 19 },
    { source: 15, target: 19 },
    { source: 16, target: 19 },
    { source: 17, target: 19 },
    { source: 18, target: 19 }
  ];

var links2 = [
    { source: 0, target: 10 },
    { source: 1, target: 11 },
    { source: 2, target: 12 },
    { source: 3, target: 13 }
]
  
  var width = 700;
  var height = 300;

  var force = d3.layout.force()
    .nodes(nodes)
    .links(links)
    .size([width, height])
    .linkDistance(50)
    .charge(-700)
    .on("tick", tick)
    .start();

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

  var colors = d3.scale.category10();

  var line = svg.append("g").selectAll("line")
    .data(force.links())
    .enter().append("line")
    .attr('class', 'link')
    .attr('stroke', function(d, i) {
      return colors(i);
    })

  var circle = svg.append("g").selectAll("circle")
    .data(force.nodes())
    .enter().append("circle")
    .attr("r", 8)
    .attr('class', 'circle')
    .attr('fill', function(d, i) {
      return colors(i);
    })
    .call(force.drag);

  var text = svg.append("g").selectAll("text")
    .data(force.nodes())
    .enter().append("text")
    .attr("x", 14)
    .attr("y", ".31em")
    .text(function(d) {
      return d.name;
    });

  function tick() {
    line.attr({
      x1: function(d) {
        return d.source.x;
      },
      y1: function(d) {
        return d.source.y;
      },
      x2: function(d) {
        return d.target.x;
      },
      y2: function(d) {
        return d.target.y;
      }
    });
    circle.attr("transform", transform);
    text.attr("transform", transform);
  }

  function transform(d) {
    return "translate(" + d.x + "," + d.y + ")";
  }
  .link {
    fill: none;
    stroke-width: 1.5px;
  }
  
  circle {
    stroke: black;
    stroke-width: 1.5px;
  }
  
  text {
    font: 10px sans-serif;
    pointer-events: none;
  }
  
  #graph {
    position: absolute;
    top: 0px;
    left: 0px;
  }
<script src="https://d3js.org/d3.v3.min.js"></script>
<!DOCTYPE html>
<meta charset="utf-8">
<body>
  <div id="root">
    <div style="background-color:lightgrey" id="graph" height="800px" width="800px">
    </div>
  </div>
</body>

Любая помощь очень ценится.

Теги:
d3.js

1 ответ

1
Лучший ответ

Ваша ссылка2 ссылается на узлы по индексу, поэтому в тике используется для индексации в массиве узлов. И лучше использовать классы для разных типов ссылок и узлов.

Ссылки, не связанные с силой, имеют тире.

var nodes = [
  { name: "node0" },
  { name: "node1" },
  { name: "node2" },
  { name: "node3" },
  { name: "node4" },
  { name: "node5" },
  { name: "node6" },
  { name: "node7" },
  { name: "node8" },
  { name: "node9" },
  { name: "node10" },
  { name: "node11" },
  { name: "node12" },
  { name: "node13" },
  { name: "node14" },
  { name: "node15" },
  { name: "node16" },
  { name: "node17" },
  { name: "node18" },
  { name: "node19" }
];

var links = [
  { source: 0, target: 9 },
  { source: 1, target: 9 },
  { source: 2, target: 9 },
  { source: 3, target: 9 },
  { source: 4, target: 9 },
  { source: 5, target: 9 },
  { source: 6, target: 9 },
  { source: 7, target: 9 },
  { source: 8, target: 9 },
  { source: 10, target: 19 },
  { source: 11, target: 19 },
  { source: 12, target: 19 },
  { source: 13, target: 19 },
  { source: 14, target: 19 },
  { source: 15, target: 19 },
  { source: 16, target: 19 },
  { source: 17, target: 19 },
  { source: 18, target: 19 }
];

var links2 = [
    { source: 0, target: 10 },
    { source: 1, target: 11 },
    { source: 2, target: 12 },
    { source: 3, target: 13 }
]

var width = 700;
var height = 300;

var force = d3.layout.force()
  .nodes(nodes)
  .links(links)
  .size([width, height])
  .linkDistance(50)
  .charge(-700)
  .on("tick", tick)
  .start();

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

var colors = d3.scale.category10();

var line = svg.append("g").selectAll(".link")
  .data(force.links())
  .enter().append("line")
  .attr('class', 'link')
  .attr('stroke', function(d, i) { return colors(i); });

var line2 = svg.append("g").selectAll(".link2")
  .data(links2)
  .enter().append("line")
  .attr('class', 'link2')
  .attr('stroke-dasharray', '5,5')
  .attr('stroke', function(d, i) { return colors(i); });

var circle = svg.append("g").selectAll(".circle")
  .data(force.nodes())
  .enter().append("circle")
  .attr("r", 8)
  .attr('class', 'circle')
  .attr('fill', function(d, i) {
    return colors(i);
  })
  .call(force.drag);

var text = svg.append("g").selectAll("text")
  .data(force.nodes())
  .enter().append("text")
  .attr("x", 14)
  .attr("y", ".31em")
  .text(function(d) {
    return d.name;
  });

function tick() {
  line.attr({
    x1: function(d) { return d.source.x; },
    y1: function(d) { return d.source.y; },
    x2: function(d) { return d.target.x; },
    y2: function(d) { return d.target.y; }
  });
  line2.attr({
    x1: function(d) { return nodes[d.source].x; },
    y1: function(d) { return nodes[d.source].y; },
    x2: function(d) { return nodes[d.target].x; },
    y2: function(d) { return nodes[d.target].y; }
  });
  circle.attr("transform", transform);
  text.attr("transform", transform);
}

function transform(d) {
  return "translate(" + d.x + "," + d.y + ")";
}
.link {
    fill: none;
    stroke-width: 1.5px;
  }
  
  circle {
    stroke: black;
    stroke-width: 1.5px;
  }
  
  text {
    font: 10px sans-serif;
    pointer-events: none;
  }
  
  #graph {
    position: absolute;
    top: 0px;
    left: 0px;
  }
<script src="https://d3js.org/d3.v3.min.js"></script>
<!DOCTYPE html>
<meta charset="utf-8">
<body>
  <div id="root">
    <div style="background-color:lightgrey" id="graph" height="800px" width="800px">
    </div>
  </div>
</body>

Ещё вопросы

Сообщество Overcoder
Наверх
Меню