From 9ef90cb862988c12961b740c8eaceed93cdb4830 Mon Sep 17 00:00:00 2001
From: Matthias Konitzny <konitzny@ibr.cs.tu-bs.de>
Date: Thu, 10 Jun 2021 17:25:30 +0200
Subject: [PATCH] Added node highlights and focus on node functions.

---
 graph.js | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 90 insertions(+), 1 deletion(-)

diff --git a/graph.js b/graph.js
index 393aeb1..0d4ffac 100644
--- a/graph.js
+++ b/graph.js
@@ -1,5 +1,94 @@
+const highlightNodes = new Set();
+const highlightLinks = new Set();
+let firstHover = true;
+let hoverNode = null;
+
 const Graph = ForceGraph3D()
 (document.getElementById('3d-graph'))
     .jsonUrl(dataset)
     .nodeLabel('id')
-    .nodeAutoColorBy('group');
\ No newline at end of file
+    .nodeAutoColorBy('group')
+    .nodeColor(node => highlightNodes.has(node) ? node === hoverNode ? 'rgb(255,0,0,1)' : 'rgba(255,160,0,0.8)' : 'rgba(0,255,255,0.6)')
+    .linkWidth(link => highlightLinks.has(link) ? 4 : 1)
+    .onNodeClick(focusOnNode)
+    .onNodeHover(nodeHover)
+    .onLinkHover(linkHover);
+
+
+function updateLinks() {
+    gData = Graph.graphData();
+    // cross-link node objects
+    gData.links.forEach(link => {
+        const a = link.source;
+        const b = link.target;
+        if (!a.neighbors) a.neighbors = [];
+        if (!b.neighbors) b.neighbors = [];
+        a.neighbors.push(b);
+        b.neighbors.push(a);
+
+        if (!a.links) a.links = [];
+        if (!b.links) b.links = [];
+        a.links.push(link);
+        b.links.push(link);
+    });
+    Graph.graphData(gData)
+}
+
+
+function focusOnNode(node) {
+    // Aim at node from outside it
+    const distance = 250;
+    const distRatio = 1 + distance/Math.hypot(node.x, node.y, node.z);
+
+    Graph.cameraPosition(
+        { x: node.x * distRatio, y: node.y * distRatio, z: node.z * distRatio }, // new position
+        node, // lookAt ({ x, y, z })
+        1000  // ms transition duration
+    );
+}
+
+function nodeHover(node) {
+
+    // no state change
+    if ((!node && !highlightNodes.size) || (node && hoverNode === node)) return;
+    if (firstHover) {
+        updateLinks();
+        firstHover = false;
+    }
+
+    highlightNodes.clear();
+    highlightLinks.clear();
+    if (node) {
+        highlightNodes.add(node);
+        node.neighbors.forEach(neighbor => highlightNodes.add(neighbor));
+        node.links.forEach(link => highlightLinks.add(link));
+    }
+
+    hoverNode = node || null;
+    updateHighlight();
+}
+
+function linkHover(link) {
+    highlightNodes.clear();
+    highlightLinks.clear();
+
+    if (link) {
+        highlightLinks.add(link);
+        highlightNodes.add(link.source);
+        highlightNodes.add(link.target);
+    }
+
+    updateHighlight();
+}
+
+function updateHighlight() {
+    // trigger update of highlighted objects in scene
+    Graph
+        .nodeColor(Graph.nodeColor())
+        .linkWidth(Graph.linkWidth())
+        .linkDirectionalParticles(Graph.linkDirectionalParticles());
+}
+
+
+
+
-- 
GitLab