Skip to content

Commit f527109

Browse files
Adding Force3D experiments
1 parent 0ddd158 commit f527109

File tree

2 files changed

+176
-0
lines changed

2 files changed

+176
-0
lines changed
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
<head>
2+
<style> body { margin: 0; } </style>
3+
4+
<script src="https://unpkg.com/3d-force-graph"></script>
5+
<script src="https://cdnjs.cloudflare.com/ajax/libs/graphlib/2.1.8/graphlib.min.js"></script>
6+
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/graphlib-dot.min.js"></script>
7+
</head>
8+
9+
<body>
10+
<div id="3d-graph"></div>
11+
12+
<script>
13+
const dot = `
14+
digraph {
15+
node [style=filled];
16+
A [color=red];
17+
B [color=green];
18+
C [color=blue];
19+
A -> B [color=purple];
20+
B -> C [color=orange];
21+
C -> A [color=cyan];
22+
}`;
23+
24+
const graphlibGraph = graphlibDot.read(dot);
25+
26+
var allNodes = [];
27+
var allLinks = [];
28+
29+
graphlibGraph.nodes().forEach(function(node) {
30+
var nodeData = graphlibGraph.node(node);
31+
allNodes.push({
32+
id: node,
33+
color: nodeData.color || 'white',
34+
});
35+
});
36+
37+
graphlibGraph.edges().forEach(function(edge) {
38+
allLinks.push({
39+
source: edge.v,
40+
target: edge.w,
41+
color: graphlibGraph.edge(edge).color || 'white'
42+
});
43+
});
44+
45+
const gData = {
46+
nodes: allNodes,
47+
links: allLinks
48+
};
49+
50+
// cross-link node objects
51+
gData.links.forEach(link => {
52+
const a = gData.nodes.find(node => node.id === link.source);
53+
const b = gData.nodes.find(node => node.id === link.target);
54+
!a.neighbors && (a.neighbors = []);
55+
!b.neighbors && (b.neighbors = []);
56+
a.neighbors.push(b);
57+
b.neighbors.push(a);
58+
59+
!a.links && (a.links = []);
60+
!b.links && (b.links = []);
61+
a.links.push(link);
62+
b.links.push(link);
63+
});
64+
65+
const highlightNodes = new Set();
66+
const highlightLinks = new Set();
67+
let hoverNode = null;
68+
69+
const Graph = new ForceGraph3D(document.getElementById('3d-graph'))
70+
.graphData(gData)
71+
.nodeLabel('id')
72+
.nodeColor(node => highlightNodes.has(node) ? node === hoverNode ? 'rgb(255,0,0,1)' : 'rgba(255,160,0,0.8)' : 'rgba(0,255,255,0.6)')
73+
.linkWidth(link => highlightLinks.has(link) ? 4 : 1)
74+
.linkDirectionalParticles(link => highlightLinks.has(link) ? 4 : 0)
75+
.linkDirectionalParticleWidth(4)
76+
77+
.onNodeHover(node => {
78+
// no state change
79+
if ((!node && !highlightNodes.size) || (node && hoverNode === node)) return;
80+
81+
highlightNodes.clear();
82+
highlightLinks.clear();
83+
if (node) {
84+
highlightNodes.add(node);
85+
node.neighbors.forEach(neighbor => highlightNodes.add(neighbor));
86+
node.links.forEach(link => highlightLinks.add(link));
87+
}
88+
89+
hoverNode = node || null;
90+
91+
updateHighlight(Graph);
92+
})
93+
.onLinkHover(link => {
94+
highlightNodes.clear();
95+
highlightLinks.clear();
96+
97+
if (link) {
98+
highlightLinks.add(link);
99+
highlightNodes.add(link.source);
100+
highlightNodes.add(link.target);
101+
}
102+
103+
updateHighlight(Graph);
104+
});
105+
106+
function updateHighlight(Graph) {
107+
// trigger update of highlighted objects in scene
108+
Graph
109+
.nodeColor(Graph.nodeColor())
110+
.linkWidth(Graph.linkWidth())
111+
.linkDirectionalParticles(Graph.linkDirectionalParticles());
112+
}
113+
</script>
114+
</body>
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<head>
2+
<style> body { margin: 0; } </style>
3+
4+
<script src="https://unpkg.com/3d-force-graph"></script>
5+
<script src="https://cdnjs.cloudflare.com/ajax/libs/graphlib/2.1.8/graphlib.min.js"></script>
6+
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/graphlib-dot.min.js"></script>
7+
</head>
8+
9+
<body>
10+
<div id="3d-graph"></div>
11+
12+
<script type="module">
13+
import SpriteText from "https://esm.sh/three-spritetext";
14+
15+
const dot = `
16+
digraph {
17+
node [style=filled];
18+
A [color=red];
19+
B [color=green];
20+
C [color=blue];
21+
A -> B [color=purple];
22+
B -> C [color=orange];
23+
C -> A [color=cyan];
24+
}`;
25+
26+
const graphlibGraph = graphlibDot.read(dot);
27+
28+
var nodes = [];
29+
var links = [];
30+
31+
graphlibGraph.nodes().forEach(function(node) {
32+
var nodeData = graphlibGraph.node(node);
33+
nodes.push({
34+
id: node,
35+
color: nodeData.color || 'white',
36+
});
37+
});
38+
39+
graphlibGraph.edges().forEach(function(edge) {
40+
links.push({
41+
source: edge.v,
42+
target: edge.w,
43+
color: graphlibGraph.edge(edge).color || 'white'
44+
});
45+
});
46+
47+
const Graph = new ForceGraph3D(document.getElementById('3d-graph'))
48+
.graphData({ nodes: nodes, links: links })
49+
.nodeAutoColorBy('group')
50+
.nodeThreeObject(node => {
51+
const sprite = new SpriteText(node.id);
52+
sprite.material.depthWrite = false; // make sprite background transparent
53+
sprite.color = node.color;
54+
sprite.textHeight = 8;
55+
return sprite;
56+
});
57+
58+
// Spread nodes a little wider
59+
Graph.d3Force('charge').strength(-120);
60+
61+
</script>
62+
</body>

0 commit comments

Comments
 (0)