Vue.js 和 D3.js - 力模拟

Posted

技术标签:

【中文标题】Vue.js 和 D3.js - 力模拟【英文标题】:Vue.js and D3.js - force-simualtion 【发布时间】:2022-01-14 07:39:48 【问题描述】:

我目前正在尝试使用 Restful-Api 调用并使用信息来进行 d3.js 强制模拟。问题是,如果我使用来自 API 的数据,如果什么都没有,调用模拟处理它。如果我等待下一个滴答声this.$nextTick(simu),所有位置最终都会变成NaN。这种行为有原因吗?

const URL = 'https://jsonplaceholder.typicode.com/posts';

new Vue(
  el: '#app',
  data() 
    return 
      webGraph: 
        nodes: [],
        edges: []
      ,
      graph1: 
        nodes:[
          url:2,
          url:3,
        ],
        edges:[
          source:2, target:3,
        ]
      
    
  ,
  created() 
    axios.get(URL).then((response) => 
      let node1 = 
        url: response.data[1].id
      
      let node2 = 
        url: response.data[2].id
      
      let edge = 
        source: url:response.data[1].id,
        target: url:response.data[2].id
      
      this.webGraph.nodes.push(node1)
      this.webGraph.nodes.push(node2)
      this.webGraph.edges.push(edge)
    )
    
  d3.forceSimulation(this.webGraph.nodes)
      .force("charge", d3.forceManyBody().strength(-25))
      .force("link", d3.forceLink().id(d => d.url).links(this.webGraph.edges))
      .on('end', function() 
        console.log("done")
      );
  d3.forceSimulation(this.graph1.nodes)
      .force("charge", d3.forceManyBody().strength(-25))
      .force("link", d3.forceLink().id(d => d.url).links(this.graph1.edges))
      .on('end', function() 
        console.log("done")
      );
  

  
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <h6>webGraph</h6>
  <br> 
  <h6>graph1</h6>
</div>

【问题讨论】:

【参考方案1】:

webGraphgraphData1产生不同结果的原因是webGraph的模拟在它有数据之前就开始了。如果您将simulation 代码移到axios.get().then 内,那么您会看到它按预期工作。

const URL = 'https://jsonplaceholder.typicode.com/posts';

new Vue(
  el: '#app',
  data() 
    return 
      webGraph: 
        nodes: [],
        edges: []
      ,
      graph1: 
        nodes:[
          url:2,
          url:3,
        ],
        edges:[
          source:2, target:3,
        ]
      
    
  ,
  created() 
    axios.get(URL).then((response) => 
      let node1 = 
        url: response.data[1].id
      
      let node2 = 
        url: response.data[2].id
      
      let edge = 
        source: node1,
        target: node2
      
      
      this.webGraph = 
        nodes: [node1, node2],
        edges: [edge]
      ;
      
      d3.forceSimulation(this.webGraph.nodes)
        .force("charge", d3.forceManyBody().strength(-25))
        .force("link", d3.forceLink().id(d => d.url).links(this.webGraph.edges))
        .on('end', function() 
          console.log("done")
        );
    )

  d3.forceSimulation(this.graph1.nodes)
      .force("charge", d3.forceManyBody().strength(-25))
      .force("link", d3.forceLink().id(d => d.url).links(this.graph1.edges))
      .on('end', function() 
        console.log("done")
      );
  

  
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <h6>webGraph</h6>
  <br> 
  <h6>graph1</h6>
</div>

在您的代码中,我还更改了edge 的初始化。它表明您需要查看 variablesreferences 之间的区别。

使用let edge = source: url:response.data[1].id, target: url:response.data[2].id ,如果node1 更改,edge.source 不会。所以edge.source 不知道指向哪里。使用let edge = source: node1, target: node2 ,代码不仅更短,而且如果node1 更改,edge.source 始终是最新的。

【讨论】:

以上是关于Vue.js 和 D3.js - 力模拟的主要内容,如果未能解决你的问题,请参考以下文章

D3.js 重新启动模拟时节点跳转添加或删除节点

D3.js 网络图使用力导向布局和矩形节点

d3.js - 在力有向图组上添加背景矩形

D3.js中Force-Directed Graph详解

D3.js中Force-Directed Graph详解

如何在 Vue.JS 应用程序中使用模拟