From 2fe53c0504afd14e64f82e3b58fe5e2cce7c288c Mon Sep 17 00:00:00 2001 From: Matthias Konitzny <konitzny@ibr.cs.tu-bs.de> Date: Thu, 29 Jul 2021 16:44:02 +0200 Subject: [PATCH] More refactoring. --- config.js | 9 +++ display/graph.js | 153 +++++++++++++++++++---------------------- display/helpers.js | 15 ++++ display/infooverlay.js | 10 ++- display/linkoverlay.js | 2 +- knowledge-space.php | 17 +++-- 6 files changed, 110 insertions(+), 96 deletions(-) create mode 100644 config.js create mode 100644 display/helpers.js diff --git a/config.js b/config.js new file mode 100644 index 0000000..a1070ec --- /dev/null +++ b/config.js @@ -0,0 +1,9 @@ +const COLOR_PALETTE = [ + 'rgb(104, 169, 77)', + 'rgb(102, 75, 154)', + 'rgb(41, 171, 226)', + 'rgb(224, 133, 35)', + 'rgb(214, 207, 126)', + 'rgb(239, 65, 35)', + 'rgb(255, 255, 255)' +]; \ No newline at end of file diff --git a/display/graph.js b/display/graph.js index c339031..b0c2a23 100644 --- a/display/graph.js +++ b/display/graph.js @@ -1,19 +1,18 @@ -const colorPallette = ['rgb(104, 169, 77)', 'rgb(102, 75, 154)', 'rgb(41, 171, 226)', 'rgb(224, 133, 35)', - 'rgb(214, 207, 126)', 'rgb(239, 65, 35)', 'rgb(255, 255, 255)']; -const edgeColors = {}; -var graph_element = document.getElementById('3d-graph'); - - class Graph { constructor(dataUrl) { this.graph = null; + this.highlightNodes = new Set(); this.highlightLinks = new Set(); this.hoverNode = null; + this.edgeColors = {}; + this.firstTick = true; this.infooverlay = null; + this.loadGraph(dataUrl); + } async loadGraph(dataUrl) { @@ -43,13 +42,28 @@ class Graph { .height(getHeight()); } + initializeModel() { + if (this.firstTick) { + this.mapEdgeColors(); + this.updateLinks(); + this.addBackground(); + + // Catch resize events + getCanvasDivNode().addEventListener("fullscreenchange", this.resize()); + window.onresize = G.resize(); + + loadComponents(); + this.firstTick = false; + } + } + getNodeColor(node) { return this.highlightNodes.has(node) ? node === hoverNode ? 'rgb(255,0,0,1)' : 'rgba(255,160,0,0.8)' : 'rgba(0,255,255,0.6)'; } getLinkColor(link) { if ('type' in link) { - return edgeColors[link.type] + return this.edgeColors[link.type] } return 'rgb(255, 255, 255)' } @@ -58,6 +72,12 @@ class Graph { return this.highlightLinks.has(link) ? 2 : 0.8; } + getLinkClasses() { + const linkClasses = []; + this.graph.graphData().links.forEach(link => linkClasses.push(link.type)); + return [... new Set(linkClasses)]; + } + onNodeHover(node) { // no state change if ((!node && !this.highlightNodes.size) || (node && this.hoverNode === node)) return; @@ -86,17 +106,26 @@ class Graph { this.updateHighlight(); } - getLinkClasses() { - const linkClasses = []; - this.graph.graphData().links.forEach(link => linkClasses.push(link.type)); - return [... new Set(linkClasses)]; + focusOnNode(node) { + // Aim at node from outside it + const distance = 250; + const distRatio = 1 + distance/Math.hypot(node.x, node.y, node.z); + + this.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 + ); } - mapEdgeColors() { - const linkClasses = this.getLinkClasses() - for (let i = 0; i < linkClasses.length; i++) { - edgeColors[linkClasses[i]] = colorPallette[i % colorPallette.length] - } + focusOnNodeId(id) { + const gData = this.graph.graphData(); + + gData.nodes.forEach(node => { + if (node.id === id) { + this.onNodeClick(node); + } + }) } updateLinks() { @@ -126,6 +155,16 @@ class Graph { .linkDirectionalParticles(this.graph.linkDirectionalParticles()); } + resize() { + if(document.fullscreenElement == getCanvasDivNode()) { + this.graph.height(screen.height); + this.graph.width(screen.width); + } else { + this.graph.height(window.innerHeight - 200); + this.graph.width(getWidth()); + } + } + addBackground() { const sphereGeometry = new THREE.SphereGeometry(20000, 32, 32); //const planeGeometry = new THREE.PlaneGeometry(1000, 1000, 1, 1); @@ -139,42 +178,18 @@ class Graph { this.graph.scene().add(mesh); } - focusOnNode(node) { - // Aim at node from outside it - const distance = 250; - const distRatio = 1 + distance/Math.hypot(node.x, node.y, node.z); - - this.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 - ); - } - - focusOnNodeId(id) { - const gData = this.graph.graphData(); - - gData.nodes.forEach(node => { - if (node.id === id) { - this.onNodeClick(node); - } - }) + mapEdgeColors() { + const linkClasses = this.getLinkClasses() + for (let i = 0; i < linkClasses.length; i++) { + this.edgeColors[linkClasses[i]] = COLOR_PALETTE[i % COLOR_PALETTE.length] + } } - resizeGraph() { + resize() { this.graph.width(getWidth()); this.graph.height(getHeight()); } - initializeModel() { - if (this.firstTick) { - this.mapEdgeColors(); - this.updateLinks(); - this.addBackground(); - loadComponents(); - this.firstTick = false; - } - } drawNode(node) { // Draw node as label + image @@ -225,57 +240,27 @@ class Graph { const dataUrl = plugin_path + 'datasets/aud1.json' G = new Graph(dataUrl); linkoverlay = new LinkOverlay(G); -infooverlay = new InfoOverlay(); +infooverlay = new InfoOverlay(G); G.infooverlay = infooverlay; function loadComponents() { linkoverlay.create(); infooverlay.create(); - add_fullscreen_mode_button(); - add_fullscreen_Listener(); - window.onresize = G.resizeGraph(); + createFullScreenButton(); } -function getWidth() { - return document.getElementById('3d-graph').offsetWidth; -} -function getHeight() { - return window.innerHeight - 200 -} - -function getCanvasDivNode() { - const domNode = document.getElementById('3d-graph'); - return domNode.firstChild.firstChild.firstChild; -} - -function add_fullscreen_mode_button() { +function createFullScreenButton() { const sceneNode = document.getElementById('3d-graph'); const overlayNode = document.createElement('button'); overlayNode.className = 'fullscreen_button'; overlayNode.innerText = 'fullscreen'; - overlayNode.addEventListener("click", fullscreen_mode); + overlayNode.addEventListener("click", function () { + if(getCanvasDivNode().requestFullscreen) { + getCanvasDivNode().requestFullscreen().catch(); + } + }); sceneNode.appendChild(overlayNode); } -function fullscreen_mode(){ - if(getCanvasDivNode().requestFullscreen) { - getCanvasDivNode().requestFullscreen().catch(); - } -} - -function resize_canvas() { - if(document.fullscreenElement == getCanvasDivNode()) { - G.graph.height(screen.height); - G.graph.width(screen.width); - } else { - G.graph.height(window.innerHeight - 200); - G.graph.width(getWidth()); - } -} - -function add_fullscreen_Listener() { - getCanvasDivNode().addEventListener("fullscreenchange", resize_canvas); -} - diff --git a/display/helpers.js b/display/helpers.js new file mode 100644 index 0000000..38d9e76 --- /dev/null +++ b/display/helpers.js @@ -0,0 +1,15 @@ + +function getWidth() { + return document.getElementById('3d-graph').offsetWidth; +} + + +function getHeight() { + return window.innerHeight - 200 +} + + +function getCanvasDivNode() { + const domNode = document.getElementById('3d-graph'); + return domNode.firstChild.firstChild.firstChild; +} \ No newline at end of file diff --git a/display/infooverlay.js b/display/infooverlay.js index 854d07e..1003e20 100644 --- a/display/infooverlay.js +++ b/display/infooverlay.js @@ -1,10 +1,8 @@ - - class InfoOverlay { - constructor() { - + constructor(graph) { + this.graph = graph; } create() { @@ -63,7 +61,7 @@ class InfoOverlay { tablink.className = 'tablinks'; tablink.id = linkType + "_id"; tablink.innerHTML = linkType[0] + linkType[1] + linkType[2]; - tablink.style = "background-color: " + edgeColors[linkClasses[i]]; + tablink.style = "background-color: " + this.graph.edgeColors[linkClasses[i]]; tablink.setAttribute("onclick", "openTab(event, " + linkType + "_id)"); //unusual function call links.appendChild(tablink); @@ -77,7 +75,7 @@ class InfoOverlay { const tabcontent = document.createElement('div'); tabcontent.className = "tabcontent"; tabcontent.id = linkType + "_id_content"; - tabcontent.style = "background-color: " + edgeColors[linkClasses[i]]; + tabcontent.style = "background-color: " + this.graph.edgeColors[linkClasses[i]]; link_container.appendChild(tabcontent); } diff --git a/display/linkoverlay.js b/display/linkoverlay.js index 5c3acaa..8dc5699 100644 --- a/display/linkoverlay.js +++ b/display/linkoverlay.js @@ -23,7 +23,7 @@ class LinkOverlay { const colorStrip = document.createElement('div'); colorStrip.className = 'rel-container'; - colorStrip.style = "background-color: " + edgeColors[linkClasses[i]] + "; width: " + 10 * chars + "px;"; + colorStrip.style = "background-color: " + this.graph.edgeColors[linkClasses[i]] + "; width: " + 10 * chars + "px;"; relation.appendChild(colorStrip); } } diff --git a/knowledge-space.php b/knowledge-space.php index 65aaf3d..f2f4c07 100644 --- a/knowledge-space.php +++ b/knowledge-space.php @@ -10,7 +10,7 @@ Author: Matthias Konitzny function ks_add_graph(): string { $graph = '<script src="//unpkg.com/3d-force-graph"></script>'; - $three = '<script src="//unpkg.com/three"></script>'; + $three = '<script src="//unpkg.com/three@0.130.0"></script>'; $renderer = '<script src="//unpkg.com/three/examples/js/renderers/CSS2DRenderer.js"></script>'; $renderer2 = '<script src="//unpkg.com/three/examples/js/renderers/CSS3DRenderer.js"></script>'; $div = '<div id="3d-graph"></div>'; @@ -19,16 +19,23 @@ function ks_add_graph(): string $variables = "<script> var plugin_path = '$plugin_dir'; </script>"; - $script_path1 = $plugin_dir.'display'.DIRECTORY_SEPARATOR.'infooverlay.js'; - $script_path2 = $plugin_dir.'display'.DIRECTORY_SEPARATOR.'linkoverlay.js'; - $script_path3 = $plugin_dir.'display'.DIRECTORY_SEPARATOR.'graph.js'; + // Yeah this is pretty ugly - need packaging asap. + + $script_path0 = $plugin_dir.'config.js'; + $script_path1 = $plugin_dir.'display'.DIRECTORY_SEPARATOR.'helpers.js'; + $script_path2 = $plugin_dir.'display'.DIRECTORY_SEPARATOR.'infooverlay.js'; + $script_path3 = $plugin_dir.'display'.DIRECTORY_SEPARATOR.'linkoverlay.js'; + $script_path4 = $plugin_dir.'display'.DIRECTORY_SEPARATOR.'graph.js'; + + $script0 = "<script src='$script_path0'></script>"; $script1 = "<script src='$script_path1'></script>"; $script2 = "<script src='$script_path2'></script>"; $script3 = "<script src='$script_path3'></script>"; + $script4 = "<script src='$script_path4'></script>"; - return $three . $renderer .$renderer2 . $graph . $div . $variables . $script1 . $script2 .$script3; + return $three . $renderer .$renderer2 . $graph . $div . $variables . $script0 . $script1 . $script2 .$script3 .$script4; } function ks_add_editor(): string -- GitLab