From fbc45548f7ee80715ec74d8c249c662a26f7feae Mon Sep 17 00:00:00 2001
From: Aaron Pham <contact@aarnphm.xyz>
Date: Sat, 01 Feb 2025 21:22:29 +0000
Subject: [PATCH] feat(graph): enable radial mode (#1738)

---
 docs/features/graph view.md               |    2 ++
 quartz/components/Graph.tsx               |    5 ++++-
 quartz/components/scripts/graph.inline.ts |   11 +++++++++--
 3 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/docs/features/graph view.md b/docs/features/graph view.md
index 4f905c7..19f0862 100644
--- a/docs/features/graph view.md
+++ b/docs/features/graph view.md
@@ -36,6 +36,7 @@
     opacityScale: 1, // how quickly do we fade out the labels when zooming out?
     removeTags: [], // what tags to remove from the graph
     showTags: true, // whether to show tags in the graph
+    enableRadial: false, // whether to constrain the graph, similar to Obsidian
   },
   globalGraph: {
     drag: true,
@@ -49,6 +50,7 @@
     opacityScale: 1,
     removeTags: [], // what tags to remove from the graph
     showTags: true, // whether to show tags in the graph
+    enableRadial: true, // whether to constrain the graph, similar to Obsidian
   },
 })
 ```
diff --git a/quartz/components/Graph.tsx b/quartz/components/Graph.tsx
index ec3475d..e8b462d 100644
--- a/quartz/components/Graph.tsx
+++ b/quartz/components/Graph.tsx
@@ -18,6 +18,7 @@
   removeTags: string[]
   showTags: boolean
   focusOnHover?: boolean
+  enableRadial?: boolean
 }
 
 interface GraphOptions {
@@ -39,6 +40,7 @@
     showTags: true,
     removeTags: [],
     focusOnHover: false,
+    enableRadial: false,
   },
   globalGraph: {
     drag: true,
@@ -53,10 +55,11 @@
     showTags: true,
     removeTags: [],
     focusOnHover: true,
+    enableRadial: true,
   },
 }
 
-export default ((opts?: GraphOptions) => {
+export default ((opts?: Partial<GraphOptions>) => {
   const Graph: QuartzComponent = ({ displayClass, cfg }: QuartzComponentProps) => {
     const localGraph = { ...defaultOptions.localGraph, ...opts?.localGraph }
     const globalGraph = { ...defaultOptions.globalGraph, ...opts?.globalGraph }
diff --git a/quartz/components/scripts/graph.inline.ts b/quartz/components/scripts/graph.inline.ts
index dbddae9..16ee33f 100644
--- a/quartz/components/scripts/graph.inline.ts
+++ b/quartz/components/scripts/graph.inline.ts
@@ -8,6 +8,7 @@
   forceCenter,
   forceLink,
   forceCollide,
+  forceRadial,
   zoomIdentity,
   select,
   drag,
@@ -87,6 +88,7 @@
     removeTags,
     showTags,
     focusOnHover,
+    enableRadial,
   } = JSON.parse(graph.dataset["cfg"]!) as D3Config
 
   const data: Map<SimpleSlug, ContentDetails> = new Map(
@@ -161,15 +163,20 @@
       })),
   }
 
+  const width = graph.offsetWidth
+  const height = Math.max(graph.offsetHeight, 250)
+
   // we virtualize the simulation and use pixi to actually render it
+  // Calculate the radius of the container circle
+  const radius = Math.min(width, height) / 2 - 40 // 40px padding
   const simulation: Simulation<NodeData, LinkData> = forceSimulation<NodeData>(graphData.nodes)
     .force("charge", forceManyBody().strength(-100 * repelForce))
     .force("center", forceCenter().strength(centerForce))
     .force("link", forceLink(graphData.links).distance(linkDistance))
     .force("collide", forceCollide<NodeData>((n) => nodeRadius(n)).iterations(3))
 
-  const width = graph.offsetWidth
-  const height = Math.max(graph.offsetHeight, 250)
+  if (enableRadial)
+    simulation.force("radial", forceRadial(radius * 0.8, width / 2, height / 2).strength(0.3))
 
   // precompute style prop strings as pixi doesn't support css variables
   const cssVars = [

--
Gitblit v1.10.0