index.html 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. <head>
  2. <style> body { margin: 0; } </style>
  3. <script src="//unpkg.com/3d-force-graph"></script>
  4. <!-- <script src="../../dist/3d-force-graph.js"></script>-->
  5. <style>
  6. .clickable { cursor: unset !important }
  7. </style>
  8. </head>
  9. <body>
  10. <div id="3d-graph"></div>
  11. <script>
  12. const rootId = 0;
  13. // Random tree
  14. const N = 300;
  15. const gData = {
  16. nodes: [...Array(N).keys()].map(i => ({ id: i, collapsed: i !== rootId, childLinks: [] })),
  17. links: [...Array(N).keys()]
  18. .filter(id => id)
  19. .map(id => ({
  20. source: Math.round(Math.random() * (id - 1)),
  21. target: id
  22. }))
  23. };
  24. // link parent/children
  25. const nodesById = Object.fromEntries(gData.nodes.map(node => [node.id, node]));
  26. gData.links.forEach(link => {
  27. nodesById[link.source].childLinks.push(link);
  28. });
  29. const getPrunedTree = () => {
  30. const visibleNodes = [];
  31. const visibleLinks = [];
  32. (function traverseTree(node = nodesById[rootId]) {
  33. visibleNodes.push(node);
  34. if (node.collapsed) return;
  35. visibleLinks.push(...node.childLinks);
  36. node.childLinks
  37. .map(link => ((typeof link.target) === 'object') ? link.target : nodesById[link.target]) // get child node
  38. .forEach(traverseTree);
  39. })(); // IIFE
  40. return { nodes: visibleNodes, links: visibleLinks };
  41. };
  42. const elem = document.getElementById('3d-graph');
  43. const Graph = ForceGraph3D()(elem)
  44. .graphData(getPrunedTree())
  45. .linkDirectionalParticles(2)
  46. .nodeColor(node => !node.childLinks.length ? 'green' : node.collapsed ? 'red' : 'yellow')
  47. .onNodeHover(node => elem.style.cursor = node && node.childLinks.length ? 'pointer' : null)
  48. .onNodeClick(node => {
  49. if (node.childLinks.length) {
  50. node.collapsed = !node.collapsed; // toggle collapse state
  51. Graph.graphData(getPrunedTree());
  52. }
  53. });
  54. </script>
  55. </body>