как добавить узлы и ссылки сделать d3-force без ввода - PullRequest
1 голос
/ 06 ноября 2019

Я пытаюсь обновить узлы и ссылки, но хотел бы не использовать шаблон ввода d3. Причина в том, что я хочу, чтобы среда svelte сделала это вместо этого, а также обрабатывала весь рендеринг, я просто хочу использовать d3-force для вычислений.

Первоначальный рендер работает нормально, но при добавлении ссылок и узлов возникают следующие проблемы:

  1. при добавлении ссылок сеть увеличивается
  2. ссылки не работаютПохоже, что они не влияют на макет графа, то есть они не добавляются в force.simulation
  3. . Первое добавление узлов, кажется, работает, но при добавлении узлов после добавления ссылки они не отображаются. Похоже, что силы извлекаются из других узлов.

Вот мои функции для добавления узлов и ссылок:

function addNode(){
    force.forceSimulation(data.nodes.push({"id": "116", "group": 5, "index":data.nodes.length, "x":0, "y":0, "vx":0, "vy":0}))
    data=data
    graph.alpha(1.0).update()
    graph.restart()

}

function addLink(){
    let n=getRandomInt(0, data.nodes.length-1)
    let tn=getRandomInt(0, n)
    let sn=getRandomInt(n, data.nodes.length-1)

    graph.force("link", force.forceLink(data.links.push({'source':data.nodes[sn], 'target':data.nodes[tn],'index':data.links.length, 'value':getRandomInt(1, 7)})))

    data=data

    graph.alpha(1.0).update()
    graph.restart()
}

Я нашел этот ответ, но они используютобъединить и привязать его к элементам DOM. Я не понимаю, как я могу сделать это без отношения к DOM, просто обновив массив узлов и ссылок в javascript, чтобы d3-force включил его в симуляцию.

Здесь У меня есть текущая симуляция в svelte REPL, вы можете раскошелиться и отредактировать ее.

1 Ответ

1 голос
/ 06 ноября 2019

К счастью, отсоединение раскладки d3-force от DOM довольно просто: сама раскладка Force не взаимодействует с DOM, это просто физический расчет, основанный на свойствах некоторых данных. Добавление и удаление точек данных (узлов / ссылок) может быть немного сложным, но это одно и то же, независимо от того, визуализирует ли D3 DOM, что-то еще, или вы вообще не оказываете силу.

Здесь вы добавляете ссылки и узлы:

function addNode(){
    force.forceSimulation(data.nodes.push({"id": "116", "group": 5, "index":data.nodes.length, "x":0, "y":0, "vx":0, "vy":0}))
    data=data
    graph.alpha(1.0).update()
    graph.restart()
}

function addLink(){
    let n=getRandomInt(0, data.nodes.length-1)
    let tn=getRandomInt(0, n)
    let sn=getRandomInt(n, data.nodes.length-1)

    graph.force("link", force.forceLink(data.links.push({'source':data.nodes[sn], 'target':data.nodes[tn],'index':data.links.length, 'value':getRandomInt(1, 7)})))

    data=data

    graph.alpha(1.0).update()
    graph.restart()
}

Здесь есть несколько проблем:

  1. Array.push () не возвращает массив. Он изменяет массив на месте, возвращая длину массива после нажатия элемента. Это означает, что вы на самом деле не добавляете узлы к макету форсировки. Это вызовет проблемы, так как для принудительного размещения требуются объекты, а не примитивы для представления узлов. Вместо этого просто нажмите узел / ссылку, затем передайте массив узла / ссылки в .nodes () или .links ()

  2. force.forceSimulation () создаст новый генератор раскладки силы,это не то, что вы хотите. Вы хотите добавить узлы к существующим узлам, поэтому мы можем использовать graph.nodes().

  3. Нет force.update(), это вызывает ошибку и поэтому вы не можете перезапуститьсимуляция, как только это сделано, остывает. Мы можем просто отбросить эту часть.

Давайте посмотрим, как эти две функции выглядят корректирующими для этого:

function addNode(){
    data.nodes.push({"id": "116", "group": 5, "index":data.nodes.length, "x":0, "y":0, "vx":0, "vy":0})
    graph.nodes(data.nodes)
    data=data
    graph.alpha(1.0).restart()

}

function addLink(){
    let n=getRandomInt(0, data.nodes.length-1)
    let tn=getRandomInt(0, n)
    let sn=getRandomInt(n, data.nodes.length-1)

  data.links.push({'source':data.nodes[sn], 'target':data.nodes[tn],'index':data.links.length, 'value':getRandomInt(1, 7)})
    graph.force("link", force.forceLink(data.links))
    data=data
    graph.alpha(1.0).restart()

}

Я не уверен, почему выесть data=data, я не вижу никакой разницы без него, я спокойно предположу, что это причуды фреймворка


Небольшая альтернатива для обновления ссылок:

Вы можетеполучите доступ к силе, которую вы назвали «ссылка», и назначьте ей новые ссылки с помощью:

graph.force("link").links(data.links)

Вместо:

graph.force("link", force.forceLink(data.links))

Последний воссоздает силу, где первый просто изменяетэто.

...