英文:
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("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"}];
/* initialize forces */
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)
;
/* create circes based on 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; })
;
/* make transition */
function ticked()
{
nodes
.attr("cx", function (d) { return d.x; })
.attr("cy", function(d) { return d.y; })
;
};
/* call update */
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()
;
//simulation.force("x").initialize(data2);
//simulation.force("y").initialize(data2);
//simulation.force("charge").initialize(data2);
}
<!-- language: lang-css -->
svg {
display: block;
}
html, body {
margin: 0;
padding: 0;
height: 100%;
background-color: #ffffff;
}
<!-- language: lang-html -->
<!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>
<!-- 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("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"}];
/* initialize forces */
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)
;
/* create circes based on 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; })
;
/* make transition */
function ticked()
{
nodes
.attr("cx", function (d) { return d.x; })
.attr("cy", function(d) { return d.y; })
;
};
/* call update */
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()
;
//simulation.force("x").initialize(data2);
//simulation.force("y").initialize(data2);
//simulation.force("charge").initialize(data2);
}
<!-- language: lang-css -->
svg {
display: block;
}
html, body {
margin: 0;
padding: 0;
height: 100%;
background-color: #ffffff;
}
<!-- language: lang-html -->
<!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>
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论