我正在尝试更新节点和链接,但不想使用d3的enter模式。原因是我想要苗条的框架来做这件事以及处理所有渲染,我只想使用d3-force进行计算。
我使初始渲染正常工作,但是添加链接和节点存在以下问题:
这是我添加节点和链接的功能:
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()
}
我找到了this答案,但他们使用merge并将其绑定到DOM元素。我不了解如何在不涉及DOM的情况下如何做到这一点,只是更新了javascript中的节点和链接数组以使d3-force将其包含在仿真中。
[Here我在一个苗条的REPL中拥有当前模拟,您可以对其进行分叉和编辑。
幸运的是,将d3力布局与DOM解除关联非常容易:力布局本身与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))
后者重现了力量,而前者只是对其进行了修改。