I got an D3v4 graph in place, where I can dynamical add nodes. My problem is that each added node draws the link above the selected node. Adjusting the z-index seems nothing to change. The addNode()
creates a new link and new node for now. The node is a mix between hard coded and dynamical yet. Further I push the newly created link to the original graph array and the same for the node.
Any hints how I can fix the problem?
In following the addNode()
I am using:
function addNode(d) {
var newid = graph.nodes.length
var newLink = { source: newid, target: d.id, type: "uses" }
graph.links.push(newLink)
graph.nodes.push({
"id": newid,
"type": "software",
"name": "Node",
"icon": "\ue084",
"parent": d.id,
"level": d.level + 1,
"childs": false,
"context": [
{
"name": d.name
}
],
})
link = svg.selectAll(".link")
.data(graph.links)
.enter()
.append("line")
.attr("class", "link")
.style("pointer-events", "none")
.attr('marker-end', 'url(#arrowhead)')
.style("display", "block")
.merge(link)
linkPaths = svg.selectAll(".linkPath")
.data(graph.links)
.enter()
.append('path')
.style("pointer-events", "none")
.attrs({
'class': 'linkPath',
'fill-opacity': 1,
'stroke-opacity': 1,
'id': function (d, i) { return 'linkPath' + i }
})
.merge(linkPaths)
linkLabels = svg.selectAll(".linkLabel")
.data(graph.links)
.enter()
.append('text')
.style("pointer-events", "none")
.attrs({
'class': 'linkLabel',
'id': function (d, i) { return 'linkLabel' + i },
'font-size': 12,
'fill': 'black'
})
.merge(linkLabels)
linkLabels.append('textPath')
.attr('xlink:href', function (d, i) { return '#linkPath' + i })
.style("text-anchor", "middle")
.style("pointer-events", "none")
.attr("startOffset", "50%")
.text(function (d) { return d.type })
.merge(linkLabels)
node = svg.selectAll(".node")
.data(graph.nodes)
.enter()
.append("g")
.attr("class", "node")
.attr("stroke", "white")
.attr("stroke-width", "2px")
.call(d3.drag()
.on("start", dragStarted)
.on("drag", dragged)
.on("end", dragEnded)
)
.on("contextmenu", d3.contextMenu(menu))
.merge(node)
node.append("circle")
.attr("r", 30)
.style("fill", initialNodeColor)
.on("mouseenter", mouseEnter)
.on("mouseleave", mouseLeave)
.on("click", click)
.on("dblclick", dblclick)
.on("contextmenu", d3.contextMenu(menu))
.merge(node)
node.append("text")
.style("class", "icon")
.attr("font-family", "FontAwesome")
.attr("dominant-baseline", "central")
.attr("text-anchor", "middle")
.attr("font-size", 30)
.attr("fill", "black")
.attr("stroke-width", "0px")
.attr("pointer-events", "none")
.text(function (d) { return d.icon })
.on("contextmenu", d3.contextMenu(menu))
.merge(node)
simulation.nodes(graph.nodes);
simulation.force("link").links(graph.links);
//reheat the simulation
simulation.alpha(0.3).restart()
}
Z-index doesn't work on svg. Svg will draw elements by the order they appear.
So you need to add the nodes after the links, so they are on top.
Because you are adding new nodes/links at a later stage, you can do this:
var linksContainer = svg.append('g').attr('class', 'linksContainer');
var nodesContainer = svg.append('g').attr('class', 'nodesContainer');
Eg: (I hope I didn't miss any svg)
function addNode(d) {
var newid = graph.nodes.length
var newLink = { source: newid, target: d.id, type: "uses" }
graph.links.push(newLink)
graph.nodes.push({
"id": newid,
"type": "software",
"name": "Node",
"icon": "\ue084",
"parent": d.id,
"level": d.level + 1,
"childs": false,
"context": [
{
"name": d.name
}
],
})
link = linksContainer.selectAll(".link")
.data(graph.links)
.enter()
.append("line")
.attr("class", "link")
.style("pointer-events", "none")
.attr('marker-end', 'url(#arrowhead)')
.style("display", "block")
.merge(link)
linkPaths = linksContainer.selectAll(".linkPath")
.data(graph.links)
.enter()
.append('path')
.style("pointer-events", "none")
.attrs({
'class': 'linkPath',
'fill-opacity': 1,
'stroke-opacity': 1,
'id': function (d, i) { return 'linkPath' + i }
})
.merge(linkPaths)
linkLabels = linksContainer.selectAll(".linkLabel")
.data(graph.links)
.enter()
.append('text')
.style("pointer-events", "none")
.attrs({
'class': 'linkLabel',
'id': function (d, i) { return 'linkLabel' + i },
'font-size': 12,
'fill': 'black'
})
.merge(linkLabels)
linkLabels.append('textPath')
.attr('xlink:href', function (d, i) { return '#linkPath' + i })
.style("text-anchor", "middle")
.style("pointer-events", "none")
.attr("startOffset", "50%")
.text(function (d) { return d.type })
.merge(linkLabels)
node = nodesContainer.selectAll(".node")
.data(graph.nodes)
.enter()
.append("g")
.attr("class", "node")
.attr("stroke", "white")
.attr("stroke-width", "2px")
.call(d3.drag()
.on("start", dragStarted)
.on("drag", dragged)
.on("end", dragEnded)
)
.on("contextmenu", d3.contextMenu(menu))
.merge(node)
node.append("circle")
.attr("r", 30)
.style("fill", initialNodeColor)
.on("mouseenter", mouseEnter)
.on("mouseleave", mouseLeave)
.on("click", click)
.on("dblclick", dblclick)
.on("contextmenu", d3.contextMenu(menu))
.merge(node)
node.append("text")
.style("class", "icon")
.attr("font-family", "FontAwesome")
.attr("dominant-baseline", "central")
.attr("text-anchor", "middle")
.attr("font-size", 30)
.attr("fill", "black")
.attr("stroke-width", "0px")
.attr("pointer-events", "none")
.text(function (d) { return d.icon })
.on("contextmenu", d3.contextMenu(menu))
.merge(node)
simulation.nodes(graph.nodes);
simulation.force("link").links(graph.links);
//reheat the simulation
simulation.alpha(0.3).restart()
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.