diff --git a/galaxy/templates/galaxy/user.jinja b/galaxy/templates/galaxy/user.jinja
index 574cc824..38abb6de 100644
--- a/galaxy/templates/galaxy/user.jinja
+++ b/galaxy/templates/galaxy/user.jinja
@@ -7,9 +7,9 @@
{% block content %}
{% if object.current_star %}
-
+
-
+
Reset on {{ object.get_display_name() }}
Self score: {{ object.current_star.mass }}
@@ -58,9 +58,31 @@
return Graph.graphData().nodes.find(n => n.id === id);
}
+ function get_links_from_node_id(id) {
+ return Graph.graphData().links.filter(l => l.source.id === id || l.target.id === id);
+ }
+
function focus_node(node) {
+ highlightNodes.clear();
+ highlightLinks.clear();
+
+ hoverNode = node || null;
+ if (node) { // collect neighbors and links for highlighting
+ get_links_from_node_id(node.id).forEach(link => {
+ highlightLinks.add(link);
+ highlightNodes.add(link.source);
+ highlightNodes.add(link.target);
+ });
+ }
+
+ // refresh node and link display
+ Graph
+ .nodeThreeObject(Graph.nodeThreeObject())
+ .linkWidth(Graph.linkWidth())
+ .linkDirectionalParticles(Graph.linkDirectionalParticles());
+
// Aim at node from outside it
- const distance = 200;
+ const distance = 42;
const distRatio = 1 + distance/Math.hypot(node.x, node.y, node.z);
const newPos = node.x || node.y || node.z
@@ -74,25 +96,44 @@
);
}
+ const highlightNodes = new Set();
+ const highlightLinks = new Set();
+ let hoverNode = null;
+
document.addEventListener("DOMContentLoaded", () => {
+ var graph_div = document.getElementById('3d-graph');
Graph = ForceGraph3D();
- Graph(document.getElementById('3d-graph'));
+ Graph(graph_div);
Graph
.jsonUrl('{{ url("galaxy:data") }}')
- .width(1000)
- .height(700)
- .nodeAutoColorBy('id')
- .nodeLabel(node => `${node.name}`)
- .onNodeClick(node => focus_node(node))
- .linkDirectionalParticles(3)
- .linkDirectionalParticleWidth(0.8)
- .linkDirectionalParticleSpeed(0.006)
+ .width(graph_div.parentElement.clientWidth > 1200 ? 1200 : graph_div.parentElement.clientWidth) // Not perfect at all. JS-fu master from the future, please fix this :-)
+ .height(1000)
+ .enableNodeDrag(false) // allow easier navigation
+ .onNodeClick(node => {
+ camera = Graph.cameraPosition();
+ var distance = Math.sqrt(Math.pow(node.x - camera.x, 2) + Math.pow(node.y - camera.y, 2) + Math.pow(node.z - camera.z, 2))
+ if (distance < 120 || highlightNodes.has(node)) {
+ focus_node(node);
+ }
+ })
+ .linkWidth(link => highlightLinks.has(link) ? 0.4 : 0.0)
+ .linkColor(link => highlightLinks.has(link) ? 'rgba(255,160,0,1)' : 'rgba(128,255,255,0.6)')
+ .linkVisibility(link => highlightLinks.has(link))
+ .nodeVisibility(node => highlightNodes.has(node) || node.mass > 4)
+ // .linkDirectionalParticles(link => highlightLinks.has(link) ? 3 : 1) // kinda buggy for now, and slows this a bit, but would be great to help visualize lanes
+ .linkDirectionalParticleWidth(0.2)
+ .linkDirectionalParticleSpeed(-0.006)
.nodeThreeObject(node => {
const sprite = new SpriteText(node.name);
sprite.material.depthWrite = false; // make sprite background transparent
- sprite.color = node.color;
- sprite.textHeight = 5;
+ sprite.color = highlightNodes.has(node) ? node === hoverNode ? 'rgba(200,0,0,1)' : 'rgba(255,160,0,0.8)' : 'rgba(0,255,255,0.2)';
+ sprite.textHeight = 2;
+ sprite.center = new THREE.Vector2(1.2, 0.5);
return sprite;
+ })
+ .onEngineStop( () => {
+ focus_node(get_node_from_id({{ object.id }}));
+ Graph.onEngineStop(() => {}); // don't call ourselves in a loop while moving the focus
});
// Set distance between stars
@@ -103,9 +144,6 @@
Graph.d3Force('positionX', d3.forceX().strength(node => { return 1 - (1 / node.mass); }));
Graph.d3Force('positionY', d3.forceY().strength(node => { return 1 - (1 / node.mass); }));
Graph.d3Force('positionZ', d3.forceZ().strength(node => { return 1 - (1 / node.mass); }));
-
- // Focus current user
- setTimeout(() => focus_node(get_node_from_id({{ object.id }})), 1000);
})
{% endblock %}