Моя цель состоит в том, чтобы анимация появлялась после анимации некоторых дуг на графике ar c. Сначала я размещаю узлы, затем щелкаю пользователя, выделяю щелкающий (исходный) узел и анимирую дуги. Что я не могу сделать, так это анимацию целевых узлов после того, как дуги закончили анимацию. Я думаю, что происходит то, что узлы получают новые цвета, но затем перезаписываются, потому что on ("end") выполняется для всех узлов и всех дуг. Я не знаю, как заставить его работать только для целей выбранного исходного узла. Вот мой код.
// adapted from https://www.d3-graph-gallery.com/graph/arc_highlight.html
// and https://www.d3-graph-gallery.com/arc
animateArcsFromNodesForEach = {
const radius = 8;
const container = d3.select(DOM.svg(width+margin.left+margin.right,
height+margin.top+margin.bottom))
const arcGroup = container
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
// create the nodes
const nodes = arcGroup.selectAll("nodes")
.data(graphData.nodes)
.enter().append("circle")
.attr("cx", d => xScale(d.name))
.attr("cy", height-50)
.attr("r", radius)
.attr("fill", "steelblue")
// create the node labels
arcGroup.selectAll("nodeLabels")
.data(graphData.nodes)
.enter().append("text")
.attr("x", d => xScale(d.name))
.attr("y", height-20)
.attr("fill", "darkgrey")
.style("text-anchor", "middle")
.text(d => d.name)
// This code builds up the SVG path element; see nodesAndArcs for details
function buildArc(d) {
let start = xScale(idToNode[d.source].name);
let end = xScale(idToNode[d.target].name);
const arcPath = ['M', start, height-50, 'A', (start - end)/2, ',', (start-end)/2, 0,0,",",
start < end ? 1: 0, end, height-50].join(' ');
return arcPath;
}
// create the arcs
let arcs = arcGroup.selectAll("arcs")
.data(graphData.links)
.enter().append("path")
.style("fill", "none")
.attr("stroke", "none")
.attr("d", d => buildArc(d));
// When the user mouses over a node,
// add interactive highlighting to see connections between nodes
nodes.on('mouseover', function(d) {
// highlight only the selected node
d3.select(this).style("fill", "firebrick");
// next, style the arcs
arcs
// the arc color and thickness stays as the default unless connected to the selected node d
// notice how embedding the reference to arcs within nodes.on() allows the code to connect d to arcd
// this code iterates through all the arcs so we can compare each to the selected node d
.style('stroke', function (arcd) {
return arcd.source === d.id ? 'firebrick' : 'none';})
.style('stroke-width', function (arcd) {
return arcd.source === d.id ? 4 : 1;})
.attr("stroke-dasharray", function(arcd) {
return arcd.source === d.id ? this.getTotalLength() : 0;})
.attr("stroke-dashoffset", function(arcd)
{ return arcd.source === d.id ? this.getTotalLength() : 0;})
// reveal the arcs
.transition()
.duration(3000)
.attr("stroke-dashoffset", 0)
// this is the part that isn't working
.on("end", function(arcd) {
nodes
.transition().style("fill", function(nd) {
return ((d.id === arcd.source) && (nd.id === arcd.target)) ? 'firebrick' : 'steelblue';
})
})
});
// remove highlighting when user mouse moves out of node by restoring default colors and thickness
nodes.on('mouseout', function () {
nodes.style("fill", "steelblue");
arcs.style('stroke', 'none');
arcs.style('stroke-width', 1);
});
return container.node();
}