Я использую Angular 6 & D3v4 для создания диаграммы симуляции сил, и она загружается просто отлично с первого раза, и я добавил событие click в круги и текст, который обновляет данные, однако переходы работают странно - некоторые узлы удалены, но для остальных узлов добавлен новый круг и текст ... Я попробовал общий шаблон обновления от Майка Бостока, но, похоже, он не работает для меня в Angular (или может быть, это более новая версия D3?) ... вот что я делаю:
ngOnInit() {
// get data from service
this.service.getGraphData(this.id).subscribe(results => {
this.graphData = results;
this.forceSimulation = d3.forceSimulation(this.graphData)
// push nodes apart to space them out
.force("charge", d3.forceManyBody().strength(-100))
// add some collision detection so they don't overlap
.force("collide", d3.forceCollide().radius(55))
// and draw them around the centre of the space
.force("center", d3.forceCenter(this.width / 2, this.height / 2));
this.link = this.svg.selectAll(".link").data(this.graphData.links)
.enter()
.append("path")
.attr("class", "link")
.attr('stroke', "#FFF");
this.node = this.svg.selectAll(".node")
.data(this.graphData.nodes)
.enter()
.append('g');
this.updateGraph();
});
}
updateGraph() {
let graphComponent = this;
//start building/rebuilding the graph
let t = d3.transition().duration(750);
this.link = this.link.data(this.graphData.links);
this.link.exit().remove();
this.forceSimulation
// pull nodes together based on the links between them
.force("link", d3.forceLink().id(function (d) {
return d.id;
}).strength(0.025));
// add the nodes to the graphic
this.node = this.node.data(this.graphData.nodes);
this.node.exit().remove();
this.node.transition(t).style('fill', 'blue').attr('35');
this.node.append("circle")
.attr("class", "node")
.attr("r", function (d) {
// center node = larger & blue
return d.id == graphComponent.programNode.id ? 65 : 40;
})
.attr('stroke', function (d) {
// apply red border to nodes
return 'red';
})
.attr('stroke-width', function (d) {
return d.id == graphComponent.programNode.id ? 0 : 3;
})
.attr("fill", function (d) {
return d.id == graphComponent.programNode.id ? 'blue' : '#FFF';
})
.on('click', function (d) {
if (d.id !== graphComponent.programNode.id) {
graphComponent.currentLevel++;
graphComponent.componentClicked(d.programId);
}
});
// add a label to each node
this.node.append("text")
.attr('x', 0)
.attr('y', function (d) {
return d.name.length > 10 ? -20 : 0;
})
.attr('text-anchor', 'middle')
.attr("dy", "0").merge(this.node)
.text(function (d) {
return d.name.replace(/\w\S*/g, function (txt) {
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
});
})
.style("stroke", function (d) {
return d.id == graphComponent.programNode.id ? 'white' : 'black'
})
.style("stroke-width", .70)
.style("fill", function (d) {
return d.id == graphComponent.programNode.id ? '#FFF' : '#000';
})
.call(graphComponent.wrap, 35) // fit text inside of node circle
.on('click', function (d) {
if (d.programId !== graphComponent.programNode.id) {
graphComponent.currentLevel++;
graphComponent.componentClicked(d.programId);
}
});
// Update and restart the simulation.
this.forceSimulation.nodes(this.graphData.nodes)
.force("collide", d3.forceCollide().strength(1).radius(55).iterations(1))
.on("tick", ticked);
this.forceSimulation
.force("link")
.links(this.graphData.links);
// on each tick, update node and link positions
// draws links and moves nodes' x & y positions inside the svg
function ticked() {
graphComponent.link.attr('d', graphComponent.positionLink);
graphComponent.node.attr("transform", graphComponent.positionNode);
}
}
Итак ... после обновления я получаю
<g transform="translate(..., ...)>
<circle class="node" ...></circle>
<text ...>First call's text</text>
<circle class="node" ...></circle>
<text ...>Second call's text</text>
</g>
Я просто хочу удалить первый круг и текст ... есть предложения?
Заранее спасибо!