Update modular_graph_and_candidates.py
#1
by
sergiopaniego
HF Staff
- opened
modular_graph_and_candidates.py
CHANGED
|
@@ -960,6 +960,14 @@ const zoomBehavior = d3.zoom()
|
|
| 960 |
.on('zoom', handleZoom);
|
| 961 |
svg.call(zoomBehavior);
|
| 962 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 963 |
const g = svg.append('g');
|
| 964 |
|
| 965 |
// Time scale for chronological positioning with much wider spread
|
|
@@ -1036,6 +1044,16 @@ const link = g.selectAll('path.link')
|
|
| 1036 |
.attr('fill', 'none')
|
| 1037 |
.attr('stroke-width', d => d.cand ? 2.5 : 1.5);
|
| 1038 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1039 |
// Nodes with improved positioning strategy
|
| 1040 |
const node = g.selectAll('g.node')
|
| 1041 |
.data(timeline.nodes)
|
|
@@ -1043,6 +1061,16 @@ const node = g.selectAll('g.node')
|
|
| 1043 |
.attr('class', d => `node ${d.cls}`)
|
| 1044 |
.call(d3.drag().on('start', dragStart).on('drag', dragged).on('end', dragEnd));
|
| 1045 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1046 |
const baseSel = node.filter(d => d.cls === 'base');
|
| 1047 |
baseSel.append('circle').attr('r', 20).attr('fill', '#ffbe0b');
|
| 1048 |
node.filter(d => d.cls !== 'base').append('circle').attr('r', 18);
|
|
@@ -1069,10 +1097,10 @@ timeline.nodes.forEach((d, i) => {
|
|
| 1069 |
// Enhanced force simulation for optimal horizontal chronological layout
|
| 1070 |
const sim = d3.forceSimulation(timeline.nodes)
|
| 1071 |
.force('link', d3.forceLink(timeline.links).id(d => d.id)
|
| 1072 |
-
.distance(d => d.cand ?
|
| 1073 |
.strength(d => d.cand ? 0.1 : 0.3))
|
| 1074 |
-
.force('charge', d3.forceManyBody().strength(-
|
| 1075 |
-
.force('collide', d3.forceCollide(d =>
|
| 1076 |
|
| 1077 |
// Very strong chronological X positioning for proper horizontal spread
|
| 1078 |
if (timeScale) {
|
|
|
|
| 960 |
.on('zoom', handleZoom);
|
| 961 |
svg.call(zoomBehavior);
|
| 962 |
|
| 963 |
+
svg.on("click", function(event) {
|
| 964 |
+
if (event.target.tagName === "svg") {
|
| 965 |
+
node.style("opacity", 1);
|
| 966 |
+
link.style("opacity", 1);
|
| 967 |
+
g.selectAll(".node-label").style("opacity", 1);
|
| 968 |
+
}
|
| 969 |
+
});
|
| 970 |
+
|
| 971 |
const g = svg.append('g');
|
| 972 |
|
| 973 |
// Time scale for chronological positioning with much wider spread
|
|
|
|
| 1044 |
.attr('fill', 'none')
|
| 1045 |
.attr('stroke-width', d => d.cand ? 2.5 : 1.5);
|
| 1046 |
|
| 1047 |
+
const linkedByIndex = {};
|
| 1048 |
+
timeline.links.forEach(d => {
|
| 1049 |
+
linkedByIndex[`${d.source.id},${d.target.id}`] = true;
|
| 1050 |
+
linkedByIndex[`${d.target.id},${d.source.id}`] = true;
|
| 1051 |
+
});
|
| 1052 |
+
|
| 1053 |
+
function isConnected(a, b) {
|
| 1054 |
+
return linkedByIndex[`${a.id},${b.id}`] || a.id === b.id;
|
| 1055 |
+
}
|
| 1056 |
+
|
| 1057 |
// Nodes with improved positioning strategy
|
| 1058 |
const node = g.selectAll('g.node')
|
| 1059 |
.data(timeline.nodes)
|
|
|
|
| 1061 |
.attr('class', d => `node ${d.cls}`)
|
| 1062 |
.call(d3.drag().on('start', dragStart).on('drag', dragged).on('end', dragEnd));
|
| 1063 |
|
| 1064 |
+
node.on("click", function(event, d) {
|
| 1065 |
+
// Stop click from bubbling up to svg
|
| 1066 |
+
event.stopPropagation();
|
| 1067 |
+
|
| 1068 |
+
node.style("opacity", o => isConnected(d, o) ? 1 : 0.1);
|
| 1069 |
+
link.style("opacity", o => (o.source.id === d.id || o.target.id === d.id) ? 1 : 0.1);
|
| 1070 |
+
g.selectAll(".node-label")
|
| 1071 |
+
.style("opacity", o => isConnected(d, o) ? 1 : 0.1);
|
| 1072 |
+
});
|
| 1073 |
+
|
| 1074 |
const baseSel = node.filter(d => d.cls === 'base');
|
| 1075 |
baseSel.append('circle').attr('r', 20).attr('fill', '#ffbe0b');
|
| 1076 |
node.filter(d => d.cls !== 'base').append('circle').attr('r', 18);
|
|
|
|
| 1097 |
// Enhanced force simulation for optimal horizontal chronological layout
|
| 1098 |
const sim = d3.forceSimulation(timeline.nodes)
|
| 1099 |
.force('link', d3.forceLink(timeline.links).id(d => d.id)
|
| 1100 |
+
.distance(d => d.cand ? 200 : 300)
|
| 1101 |
.strength(d => d.cand ? 0.1 : 0.3))
|
| 1102 |
+
.force('charge', d3.forceManyBody().strength(-800))
|
| 1103 |
+
.force('collide', d3.forceCollide(d => 70).strength(1))
|
| 1104 |
|
| 1105 |
// Very strong chronological X positioning for proper horizontal spread
|
| 1106 |
if (timeScale) {
|