d3 force 시뮬레이션 (버전 4에서!)에 하나씩 노드를 추가하려고하는데, 일부는 생성 된 후에 시뮬레이션에 의해 진화 된 것으로 보이지 않습니다 . d3 v4 동적으로 추가 된 노드에 작용하는 힘
현재 시뮬레이션은 함수, addNode 명 두 번 두 개 이상의 노드를 추가라고 한 노드를 할당합니다. 각각은 시뮬레이션에 추가되고 원과 선이 렌더링되고 커서 이벤트가 하나씩 추가됩니다.
노드를 클릭하면,
다음 새 노드 (기술적으로는 제 1 및 제 2 노드는 제만을위한 addNode 제 2 호출 될 때 설정되는 한, 동시에 수행된다) 연결된 커서 아래에있는 아이콘을 생성해야합니다. 이 노드는 시뮬레이션과 마찬가지로 다른 노드와 마찬가지로 진화해야합니다.
그러나, 일 동안 또는 두 개의 노드가 잘 만든 것 같다, 나중에 노드는 시뮬레이션에서 진화 할 것 같지 않습니다. 특히 노드 사이에 약간의 간격을 유지해야하는 많은 본문 강제는 작동하지 않는 것 같습니다.
내 직감 (일부 simulation.stop을 추가하여 이전 문제가 해결되었고 simulation.restart 새로운 노드가 추가되고 있었다 언제든지 명령) 노드가 시뮬레이션의 쳤다 기능에 대한 부적당 한 번에 추가되는 것입니다하지만, 이론적으로 시뮬레이션은 새로운 바디가 추가 될 때마다 일시 정지되어야합니다.
d3 v4에서 노드를 동적으로 추가하는 올바른 구현입니까, 아니면 맹 글링 된 메소드를 강조 표시하는 것의 문제입니까? This 이전 답변은 새로운 항목을 병합해야한다는 것을 깨닫도록 도와 주었지만, 힘이 거기에서 잘 작동하는 것처럼 보입니다. 도에
var w = 250;
var h = 250;
var svg = d3.select("body").append("svg");
svg.attr('width', w)
.attr('height', h);
// ensures links sit beneath nodes
svg.append("g").attr("id", "lnks")
svg.append("g").attr("id", "nds")
function new_node(id) {
this.id = id;
this.x = w/2;
this.y = h/2;
}
function new_link(source, target) {
this.source = source;
this.target = target;
}
var nodes = [];
var links = [];
var node;
var circles;
var link;
var simulation = d3.forceSimulation()
.force("link", d3.forceLink().distance(80).id(function(d) {
return d.id;
}))
.force("charge", d3.forceManyBody().strength(-1000))
.force("xPos", d3.forceX(w/2))
.force("yPos", d3.forceY(h/2))
.on('tick', ticked);
simulation.stop();
var newNode = new new_node(0);
nodes.push(newNode);
for (var i = 1; i < 3; i++) {
if (i == 3) continue;
addNode(0, i)
}
function addNode(rootId, newId) {
var newNode = new new_node(newId);
nodes.push(newNode);
var newLink = new new_link(rootId, newId);
links.push(newLink);
//adds newest link and draws it
link = svg.select("#lnks").selectAll(".link")
.data(links)
var linkEnter = link
.enter().append("line")
.attr("class", "link");
link = linkEnter.merge(link);
//adds newest node
node = svg.select("#nds").selectAll(".node")
.data(nodes)
var nodeEnter = node
.enter().append("g")
.attr("class", "node");
//draws circle on newest node
var circlesEnter = nodeEnter.append('circle')
node = nodeEnter.merge(node);
circles = d3.selectAll('circle');
simulation.stop();
simulation.nodes(nodes);
simulation.force("link")
.links(links);
restartSim();
}
//starts up the simulation and sets up the way the leaves react to interaction
function restartSim() {
simulation.restart();
circles.on('click', function(d, i) {
addNode(i, nodes.length)
})
}
function ticked() {
link
.attr("x1", function(d) {
return d.source.x;
})
.attr("y1", function(d) {
return d.source.y;
})
.attr("x2", function(d) {
return d.target.x;
})
.attr("y2", function(d) {
return d.target.y;
});
node.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
}
.link {
stroke: #bbb;
}
.node circle {
pointer-events: all;
fill: black;
stroke-width: 0px;
r: 20px
}
h1 {
color: white;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
코드는 여기 codepen : http://codepen.io/zpenoyre/pen/kkxBRW?editors=0010
: 여기
업데이트 된 코드 펜입니다. 알파가 여기서 무엇을하는지 이해하는 간단한 방법이 있습니까? "Reheating"은 나에게 매우 직관적이지 않으며 [d3 API] (https://github.com/d3/d3-force/blob/master/README.md#simulation_alpha)는 나에게별로 의미가 없습니다. 주제에. – Zephyr굉장 해요, 나는 시뮬레이션을 효과적으로 피터 밖으로 깨닫지 못했지만, 그것들을 자세히 보면서 나는 그것을 아주 분명하게 본다. 시뮬레이션 계산을 줄이고 싶지만 설정을 변경할 때마다 시뮬레이션을 다시 시작해야합니다. 감사! – Zephyr
@Zephyr 두 번째 코멘트에서 알 수 있습니다. 그러나'simulation.alphaTarget' 커밋에서 여러분이나 다른 누군가에게 좋은 추가 정보가 있습니다 : (https://github.com/d3/d3-force/commit/8a2c8590bb879c70eb2e10264b41d0200c887be9) "이것으로"원하는 "알파를 설정할 수 있습니다. 시뮬레이션을 수행하고 시뮬레이션을 원하는 값으로 부드럽게 보간하도록하십시오. 기본적으로 목표 값은 0이므로 시뮬레이션이 냉각됩니다. 그러나이 값을 으로 설정하면 드래그 상호 작용 중일 때와 같이 0이 아닌 값으로 설정됩니다 , 당신은 또한 시뮬레이션 열을 가지고 그것을 사용할 수 있습니다. " – ibgib