nodeEventHandling = {
const node = svg
.append("g")
.attr("class", "nodes")
.selectAll("circle")
.data(nodes, (d) => d.$id)
.enter()
.append("circle")
.attr("class", (d) => `cluster${d.cluster}`)
.attr("r", (d) => d.radius)
.attr("fill", (d) => color(+d.ncolor))
.call(
d3
.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended)
);
node.append("title").text((d) => d.id);
node
.style("cursor", "pointer")
.on("mouseover", function (evt, d) {
const connected = links.filter(
(link) => link.source === d || link.target === d
);
const connectedIds = connected.map((link) =>
link.source === d ? link.target.id : link.source.id
);
tooltip
.html(
`<strong>${d.display_name || d.id}</strong><br/>
Role: ${d.primary_roles || "N/A"}<br/>
Parent: ${d.cluster || "N/A"}`
)
.style("opacity", 1)
.style("left", `${evt.pageX + 10}px`)
.style("top", `${evt.pageY - 10}px`);
node.style("opacity", (n) =>
n.id === d.id || connectedIds.includes(n.id) ? 1 : 0.1
);
link.style("opacity", (l) => (connected.includes(l) ? 1 : 0.1));
text.style("opacity", (t) => (connectedIds.includes(t.id) ? 1 : 0));
hulls.style("opacity", (h) =>
h.nodes.data().some((n) => connectedIds.includes(n.id)) ? 0.2 : 0.05
);
})
.on("mousemove", (evt) => {
tooltip
.style("left", `${evt.pageX + 10}px`)
.style("top", `${evt.pageY - 10}px`);
})
.on("mouseout", () => {
tooltip.style("opacity", 0);
node.style("opacity", 1);
link.style("opacity", 1);
text.style("opacity", 0);
hulls.style("opacity", 0.2);
})
.on("click", (evt, d) => {
const clusterId = d.cluster;
return node.style("cursor", "pointer")
.on("mouseover", handleMouseOver)
.on("mousemove", handleMouseMove)
.on("mouseout", handleMouseOut)
.on("click", handleClick)
}
}