d3js проблема с несколькими сетями

Сценарий:

У меня есть d3, отображающий несколько сетей.

Он состоит из отдельных узлов, нескольких связанных узловых сетей.

Я пытаюсь подключить d3-force (симуляцию), чтобы узлы не перекрывались при перетаскивании, а вся сеть сохраняла относительное позиционирование.

Использую силу многих.

Эта проблема:

  1. Когда симуляция загружается (simulation.restart()), вся сеть продолжает расходиться. Все узлы/сети продолжают удаляться бесконечно.
  2. Даже когда узлы из одной сети перетаскиваются, все остальные сети перемещаются.

Был бы очень признателен, если бы кто-нибудь мог указать мне правильное решение.

Вот небольшая скрипка: https://jsfiddle.net/pdubey84/or0tn49k/2/

Сеть

var 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 },
  { id: "pike"  , group: 3, label: "Pikes"  , level: 1 },
  { id: "pike"  , group: 4, label: "Pikes"  , level: 1 },
  { id: "pike"  , group: 4, label: "Pikes"  , level: 1 },
  { id: "foo"  , group: 4, label: "foo"  , level: 1 },
    { id: "bar"  , group: 4, label: "bar"  , level: 1 }
]

var 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 },
    { target: "foo"  , source: "bar" , strength: 0.1 }
]



function getNodeColor(node, neighbors) {
  return 'red'
}


function getLinkColor(node, link) {
  return '000'
}

var width = window.innerWidth
var height = window.innerHeight

var svg = d3.select('svg')
svg.attr('width', width).attr('height', height)

// simulation setup with all forces
var linkForce = d3
  .forceLink()
  .id(function (link) { return link.id })
  .strength(function (link) { return link.strength })

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


var dragDrop = d3.drag().on('start', function (node) {
  node.fx = node.x
  node.fy = node.y
}).on('drag', function (node) {
  simulation.alphaTarget(0.7).restart()
  node.fx = d3.event.x
  node.fy = d3.event.y
}).on('end', function (node) {
  if (!d3.event.active) {
    simulation.alphaTarget(0)
  }
  node.fx = null
  node.fy = null
})

var linkElements = svg.append("g")
  .attr("class", "links")
  .selectAll("line")
  .data(links)
  .enter().append("line")
    .attr("stroke-width", 1)
      .attr("stroke", "rgba(50, 50, 50, 0.2)")

var nodeElements = svg.append("g")
  .attr("class", "nodes")
  .selectAll("circle")
  .data(nodes)
  .enter().append("circle")
    .attr("r", 10)
    .attr("fill", getNodeColor)
    .call(dragDrop)


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

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

person prgrmr    schedule 20.04.2017    source источник


Ответы (1)


Оба поведения ожидаемы. Вот что вы можете сделать для этих проблем:

  1. Сеть разлетается: я полагаю, вы говорите о функции перетаскивания, поскольку при загрузке симуляция выполняется всего 300 тиков. В этом случае используйте simulation.alpha вместо simulation.alphaTarget. simulation.alpha - правильный способ управления энтропией:

    simulation.alpha(0.7).restart();
    
  2. #P3# <блочная цитата> #P4#

Что вы можете сделать, так это отменить эту силу при первом перетаскивании:

simulation.force("center", null)

Вот ваша скрипка с этими двумя изменениями: https://jsfiddle.net/yjkgdgad/

person Gerardo Furtado    schedule 20.04.2017
comment
Большое спасибо за ваш ответ @Gerardo ... Я попробовал ваше решение, но проблема все та же .... Каждый раз, когда я пытаюсь перетащить компонент, каждый другой подключенный компонент начинает двигаться .... Это своего рода проблема, когда у меня много больших сетей... Мне было интересно, могу ли я каким-то образом идентифицировать каждый компонент, а затем применять силы только к этим компонентам, чтобы они не сдвинули ничего другого. Мысли? - person prgrmr; 25.04.2017
comment
Что ж, это третья проблема, которая не в вашем вопросе: это происходит потому, что вы повторно нагреваете симуляцию. - person Gerardo Furtado; 26.04.2017
comment
Привет @gerardo ... Извините, что беспокою вас этим, но я перепробовал кучу вещей, но третья проблема, о которой я упоминал, сохраняется. Вы случайно не знаете способ, с помощью которого я могу заставить несколько компонентов иметь разные силы, чтобы они не мешали друг другу? - person prgrmr; 01.05.2017
comment
Лучшая идея — опубликовать еще один вопрос: если вы спросите об этом здесь, в комментариях, я единственный, кто прочитает, но если вы зададите новый вопрос, его прочитают все! - person Gerardo Furtado; 01.05.2017