К счастью, отсоединение раскладки 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()
}
Здесь есть несколько проблем:
Array.push () не возвращает массив. Он изменяет массив на месте, возвращая длину массива после нажатия элемента. Это означает, что вы на самом деле не добавляете узлы к макету форсировки. Это вызовет проблемы, так как для принудительного размещения требуются объекты, а не примитивы для представления узлов. Вместо этого просто нажмите узел / ссылку, затем передайте массив узла / ссылки в .nodes () или .links ()
force.forceSimulation () создаст новый генератор раскладки силы,это не то, что вы хотите. Вы хотите добавить узлы к существующим узлам, поэтому мы можем использовать graph.nodes()
.
Нет 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))
Последний воссоздает силу, где первый просто изменяетэто.