-
Notifications
You must be signed in to change notification settings - Fork 290
/
index.html
73 lines (59 loc) · 2.37 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<head>
<style> body { margin: 0; } </style>
<script type="importmap">{ "imports": {
"react": "https://esm.sh/react",
"react-dom": "https://esm.sh/react-dom/client"
}}</script>
<!-- <script type="module">import * as React from 'react'; window.React = React;</script>-->
<!-- <script src="../../src/packages/react-force-graph-3d/dist/react-force-graph-3d.js" defer></script>-->
</head>
<body>
<div id="graph"></div>
<script src="//unpkg.com/@babel/standalone"></script>
<script type="text/jsx" data-type="module">
import ForceGraph3D from 'https://esm.sh/react-force-graph-3d?external=react';
import React, { useState, useMemo, useCallback } from 'react';
import { createRoot } from 'react-dom';
import { genRandomTree } from '../datasets/random-data.js';
const ExpandableGraph = ({ graphData }) => {
const rootId = 0;
const nodesById = useMemo(() => {
const nodesById = Object.fromEntries(graphData.nodes.map(node => [node.id, node]));
// link parent/children
graphData.nodes.forEach(node => {
node.collapsed = node.id !== rootId;
node.childLinks = [];
});
graphData.links.forEach(link => nodesById[link.source].childLinks.push(link));
return nodesById;
}, [graphData]);
const getPrunedTree = useCallback(() => {
const visibleNodes = [];
const visibleLinks = [];
(function traverseTree(node = nodesById[rootId]) {
visibleNodes.push(node);
if (node.collapsed) return;
visibleLinks.push(...node.childLinks);
node.childLinks
.map(link => ((typeof link.target) === 'object') ? link.target : nodesById[link.target]) // get child node
.forEach(traverseTree);
})();
return { nodes: visibleNodes, links: visibleLinks };
}, [nodesById]);
const [prunedTree, setPrunedTree] = useState(getPrunedTree());
const handleNodeClick = useCallback(node => {
node.collapsed = !node.collapsed; // toggle collapse state
setPrunedTree(getPrunedTree())
}, []);
return <ForceGraph3D
graphData={prunedTree}
linkDirectionalParticles={2}
nodeColor={node => !node.childLinks.length ? 'green' : node.collapsed ? 'red' : 'yellow'}
onNodeClick={handleNodeClick}
/>;
};
createRoot(document.getElementById('graph')).render(
<ExpandableGraph graphData={genRandomTree(600, true)}/>
);
</script>
</body>