如何添加节点和链接而无需输入即可执行d3-force

问题描述 投票:1回答:1

我正在尝试更新节点和链接,但不想使用d3的enter模式。原因是我想要苗条的框架来做这件事以及处理所有渲染,我只想使用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()
}

我找到了this答案,但他们使用merge并将其绑定到DOM元素。我不了解如何在不涉及DOM的情况下如何做到这一点,只是更新了javascript中的节点和链接数组以使d3-force将其包含在仿真中。

[Here我在一个苗条的REPL中拥有当前模拟,您可以对其进行分叉和编辑。

d3.js force-layout svelte
1个回答
0
投票

幸运的是,将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()
}

这里有一些问题:

  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))

后者重现了力量,而前者只是对其进行了修改。

© www.soinside.com 2019 - 2024. All rights reserved.