D3在替换数据并重新启动模拟后,并非所有节点都被更新。

huangapple go评论73阅读模式
英文:

D3 not all nodes are updated after replacing data and restarting simulation

问题

我正在尝试替换节点可视化的数据。我能够添加新数据,但当我重新启动模拟时,添加的节点位置没有更新。

/* 初始化力量 */
var simulation = d3.forceSimulation()
        .nodes(data1)
        .force("charge", d3.forceManyBody().strength(-100))
        .force("x", d3.forceX(width/2))
        .force("y", d3.forceY(height/2))
        .on("tick", ticked)
        ;

/* 创建基于data1的圆 */
var nodes = svg.append("g")
          .attr("class", "nodes")
          .selectAll("circle")
          .data(data1)
          .enter().append("circle")
          .attr("r", 10)
          .style("fill",function (d) { return d.color; } )
          .attr("id", function (d) { return d.id; })
           ;

/* 进行过渡 */ 
function ticked() 
{
    nodes
         .attr("cx", function (d) { return d.x; })
         .attr("cy", function(d) { return d.y; })
         ;
};

/* 调用更新 */ 
function updateData()
{
  nodes              
      .exit()
      .transition().duration(1000)
      .attr("r", 0)
      .remove()
      ;
  nodes
      .data(data2)
      .enter()
      .append("circle")
      .attr("r", 20)
      .attr("id", function (d) { return d.id; })
      .style("fill",function (d) { return d.color; } )
      ;
      
  nodes
      .attr("r", 20)
      .attr("id", function (d) { return d.id; })
      .style("fill",function (d) { return d.color; } )
      ;

      simulation.nodes(data2)
      .alpha(1).restart()
    ; 
}
svg {
  display: block;
}

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  background-color: #ffffff;
}
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="css/main.css">
</head>

<body>
    <button onclick="updateData()">updateData</button> 
    <svg width="100%" height="100%" style="background-color:rgb(255, 255, 255)"></svg>
    <script src="https://d3js.org/d3.v4.js"></script>
    <script src="js/app.js"></script>
</body>
</html>
英文:

I am trying to replace data for node visualisation. I was able to add new data but when I am restarting the simulation the nodes which were added are not updating position.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

var svg = d3.select(&quot;svg&quot;);
var width = svg.node().getBoundingClientRect().width;
var height = svg.node().getBoundingClientRect().height;
var data1 =  [{&quot;id&quot;:0, &quot;color&quot;: &quot;Red&quot;},{&quot;id&quot;:1, &quot;color&quot;: &quot;Blue&quot;}];
var data2 = [{&quot;id&quot;:0, &quot;color&quot;: &quot;Cyan&quot;},{&quot;id&quot;:1, &quot;color&quot;: &quot;Yellow&quot;},{&quot;id&quot;:2, &quot;color&quot;: &quot;Magenta&quot;}];
/* initialize forces */
var simulation = d3.forceSimulation()
.nodes(data1)
.force(&quot;charge&quot;, d3.forceManyBody().strength(-100))
.force(&quot;x&quot;, d3.forceX(width/2))
.force(&quot;y&quot;, d3.forceY(height/2))
.on(&quot;tick&quot;, ticked)
;
/* create circes based on data1 */
var nodes = svg.append(&quot;g&quot;)
.attr(&quot;class&quot;, &quot;nodes&quot;)
.selectAll(&quot;circle&quot;)
.data(data1)
.enter().append(&quot;circle&quot;)
.attr(&quot;r&quot;, 10)
.style(&quot;fill&quot;,function (d) { return d.color; } )
.attr(&quot;id&quot;, function (d) { return d.id; })
;
/* make transition */ 
function ticked() 
{
nodes
.attr(&quot;cx&quot;, function (d) { return d.x; })
.attr(&quot;cy&quot;, function(d) { return d.y; })
;
};
/* call update */ 
function updateData()
{
nodes              
.exit()
.transition().duration(1000)
.attr(&quot;r&quot;, 0)
.remove()
;
nodes
.data(data2)
.enter()
.append(&quot;circle&quot;)
.attr(&quot;r&quot;, 20)
.attr(&quot;id&quot;, function (d) { return d.id; })
.style(&quot;fill&quot;,function (d) { return d.color; } )
;
nodes
.attr(&quot;r&quot;, 20)
.attr(&quot;id&quot;, function (d) { return d.id; })
.style(&quot;fill&quot;,function (d) { return d.color; } )
;
simulation.nodes(data2)
.alpha(1).restart()
; 
//simulation.force(&quot;x&quot;).initialize(data2);
//simulation.force(&quot;y&quot;).initialize(data2);
//simulation.force(&quot;charge&quot;).initialize(data2);
}

<!-- language: lang-css -->

svg {
display: block;
}
html, body {
margin: 0;
padding: 0;
height: 100%;
background-color: #ffffff;
}

<!-- language: lang-html -->

&lt;!DOCTYPE html&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
&lt;meta charset=&quot;UTF-8&quot;&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;css/main.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;button onclick=&quot;updateData()&quot;&gt;updateData&lt;/button&gt; 
&lt;svg width=&quot;100%&quot; height=&quot;100%&quot; style=&quot;background-color:rgb(255, 255, 255)&quot;&gt;&lt;/svg&gt;
&lt;script src=&quot;https://d3js.org/d3.v4.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;js/app.js&quot;&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;

<!-- end snippet -->

I was testing Re-initializing Forces from this answer, but the number of nodes did changed in my case, so this seems to not be a solution for me.

How to update simulation for all nodes from the new dataset?

答案1

得分: 2

以下是您提供的代码的翻译部分:

似乎删除旧节点的操作不正常工作。在应用以下删除方式后,我成功地获得了正确的结果:

var svg = d3.select("svg");
var width = svg.node().getBoundingClientRect().width;
var height = svg.node().getBoundingClientRect().height;

var data1 =  [{"id":0, "color": "Red"},{"id":1, "color": "Blue"}];
var data2 = [{"id":0, "color": "Cyan"},{"id":1, "color": "Yellow"},{"id":2, "color": "Magenta"}];

/* 初始化力模拟 */
var simulation = d3.forceSimulation()
        .nodes(data1)
        .force("charge", d3.forceManyBody().strength(-100))
        .force("x", d3.forceX(width/2))
        .force("y", d3.forceY(height/2))
        .on("tick", ticked)
        ;

/* 根据data1创建圆圈 */
var nodes = svg.append("g")
          .attr("class", "nodes")
          .selectAll("circle")
          .data(data1)
          .enter().append("circle")
          .attr("r", 10)
          .style("fill", function (d) { return d.color; } )
          .attr("id", function (d) { return d.id; })
           ;

/* 进行过渡 */ 
function ticked() 
{
        nodes
             .attr("cx", function (d) { return d.x; })
             .attr("cy", function(d) { return d.y; })
             ;
};

/* 调用更新数据函数 */ 
function updateData()
{
  svg.selectAll("*").remove();    
      
  nodes = svg.append("g")
      .attr("class", "nodes")
      .selectAll("circle")
      .data(data2)
      .enter()
      .append("circle")
      .attr("r", 20)
      .attr("id", function (d) { return d.id; })
      .style("fill", function (d) { return d.color; } )
      ;
      
  nodes
      .attr("r", 20)
      .attr("id", function (d) { return d.id; })
      .style("fill", function (d) { return d.color; } )
      ;

      simulation.nodes(data2)
      .alpha(1).restart()
    ; 
}
svg {
  display: block;
}

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  background-color: #ffffff;
}
<!DOCTYPE html>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="css/main.css">
</head>

<body>
    <button onclick="updateData()">updateData</button> 
    <svg width="100%" height="100%" style="background-color:rgb(255, 255, 255)"></svg>
    <script src="https://d3js.org/d3.v4.js"></script>
    <script src="js/app.js"></script>
</body>
</html>
英文:

Seems that removing old nodes does not work correctly. After applying the way of removing below, I managed to get the proper result:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

var svg = d3.select(&quot;svg&quot;);
var width = svg.node().getBoundingClientRect().width;
var height = svg.node().getBoundingClientRect().height;
var data1 =  [{&quot;id&quot;:0, &quot;color&quot;: &quot;Red&quot;},{&quot;id&quot;:1, &quot;color&quot;: &quot;Blue&quot;}];
var data2 = [{&quot;id&quot;:0, &quot;color&quot;: &quot;Cyan&quot;},{&quot;id&quot;:1, &quot;color&quot;: &quot;Yellow&quot;},{&quot;id&quot;:2, &quot;color&quot;: &quot;Magenta&quot;}];
/* initialize forces */
var simulation = d3.forceSimulation()
.nodes(data1)
.force(&quot;charge&quot;, d3.forceManyBody().strength(-100))
.force(&quot;x&quot;, d3.forceX(width/2))
.force(&quot;y&quot;, d3.forceY(height/2))
.on(&quot;tick&quot;, ticked)
;
/* create circes based on data1 */
var nodes = svg.append(&quot;g&quot;)
.attr(&quot;class&quot;, &quot;nodes&quot;)
.selectAll(&quot;circle&quot;)
.data(data1)
.enter().append(&quot;circle&quot;)
.attr(&quot;r&quot;, 10)
.style(&quot;fill&quot;,function (d) { return d.color; } )
.attr(&quot;id&quot;, function (d) { return d.id; })
;
/* make transition */ 
function ticked() 
{
nodes
.attr(&quot;cx&quot;, function (d) { return d.x; })
.attr(&quot;cy&quot;, function(d) { return d.y; })
;
};
/* call update */ 
function updateData()
{
svg.selectAll(&quot;*&quot;).remove();    
nodes = svg.append(&quot;g&quot;)
.attr(&quot;class&quot;, &quot;nodes&quot;)
.selectAll(&quot;circle&quot;)
.data(data2)
.enter()
.append(&quot;circle&quot;)
.attr(&quot;r&quot;, 20)
.attr(&quot;id&quot;, function (d) { return d.id; })
.style(&quot;fill&quot;,function (d) { return d.color; } )
;
nodes
.attr(&quot;r&quot;, 20)
.attr(&quot;id&quot;, function (d) { return d.id; })
.style(&quot;fill&quot;,function (d) { return d.color; } )
;
simulation.nodes(data2)
.alpha(1).restart()
; 
//simulation.force(&quot;x&quot;).initialize(data2);
//simulation.force(&quot;y&quot;).initialize(data2);
//simulation.force(&quot;charge&quot;).initialize(data2);
}

<!-- language: lang-css -->

svg {
display: block;
}
html, body {
margin: 0;
padding: 0;
height: 100%;
background-color: #ffffff;
}

<!-- language: lang-html -->

&lt;!DOCTYPE html&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
&lt;meta charset=&quot;UTF-8&quot;&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;css/main.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;button onclick=&quot;updateData()&quot;&gt;updateData&lt;/button&gt; 
&lt;svg width=&quot;100%&quot; height=&quot;100%&quot; style=&quot;background-color:rgb(255, 255, 255)&quot;&gt;&lt;/svg&gt;
&lt;script src=&quot;https://d3js.org/d3.v4.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;js/app.js&quot;&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年2月26日 19:01:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/75571519.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定