feat(graph): enable radial mode

Signed-off-by: Aaron Pham <contact@aarnphm.xyz>
This commit is contained in:
Aaron Pham 2025-01-23 22:33:46 -05:00
parent 4e4930ef9c
commit adb7ad2a3c
No known key found for this signature in database
GPG Key ID: 18974753009D2BFA
3 changed files with 14 additions and 4 deletions

View File

@ -30,7 +30,7 @@ export const defaultContentPageLayout: PageLayout = {
Component.DesktopOnly(Component.Explorer()), Component.DesktopOnly(Component.Explorer()),
], ],
right: [ right: [
Component.Graph(), Component.Graph({ globalGraph: { enableRadial: true } }),
Component.DesktopOnly(Component.TableOfContents()), Component.DesktopOnly(Component.TableOfContents()),
Component.Backlinks(), Component.Backlinks(),
], ],

View File

@ -18,6 +18,7 @@ export interface D3Config {
removeTags: string[] removeTags: string[]
showTags: boolean showTags: boolean
focusOnHover?: boolean focusOnHover?: boolean
enableRadial?: boolean
} }
interface GraphOptions { interface GraphOptions {
@ -39,6 +40,7 @@ const defaultOptions: GraphOptions = {
showTags: true, showTags: true,
removeTags: [], removeTags: [],
focusOnHover: false, focusOnHover: false,
enableRadial: false,
}, },
globalGraph: { globalGraph: {
drag: true, drag: true,
@ -53,10 +55,11 @@ const defaultOptions: GraphOptions = {
showTags: true, showTags: true,
removeTags: [], removeTags: [],
focusOnHover: true, focusOnHover: true,
enableRadial: false,
}, },
} }
export default ((opts?: GraphOptions) => { export default ((opts?: Partial<GraphOptions>) => {
const Graph: QuartzComponent = ({ displayClass, cfg }: QuartzComponentProps) => { const Graph: QuartzComponent = ({ displayClass, cfg }: QuartzComponentProps) => {
const localGraph = { ...defaultOptions.localGraph, ...opts?.localGraph } const localGraph = { ...defaultOptions.localGraph, ...opts?.localGraph }
const globalGraph = { ...defaultOptions.globalGraph, ...opts?.globalGraph } const globalGraph = { ...defaultOptions.globalGraph, ...opts?.globalGraph }

View File

@ -8,6 +8,7 @@ import {
forceCenter, forceCenter,
forceLink, forceLink,
forceCollide, forceCollide,
forceRadial,
zoomIdentity, zoomIdentity,
select, select,
drag, drag,
@ -87,6 +88,7 @@ async function renderGraph(container: string, fullSlug: FullSlug) {
removeTags, removeTags,
showTags, showTags,
focusOnHover, focusOnHover,
enableRadial,
} = JSON.parse(graph.dataset["cfg"]!) as D3Config } = JSON.parse(graph.dataset["cfg"]!) as D3Config
const data: Map<SimpleSlug, ContentDetails> = new Map( const data: Map<SimpleSlug, ContentDetails> = new Map(
@ -161,15 +163,20 @@ async function renderGraph(container: string, fullSlug: FullSlug) {
})), })),
} }
const width = graph.offsetWidth
const height = Math.max(graph.offsetHeight, 250)
// we virtualize the simulation and use pixi to actually render it // 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) const simulation: Simulation<NodeData, LinkData> = forceSimulation<NodeData>(graphData.nodes)
.force("charge", forceManyBody().strength(-100 * repelForce)) .force("charge", forceManyBody().strength(-100 * repelForce))
.force("center", forceCenter().strength(centerForce)) .force("center", forceCenter().strength(centerForce))
.force("link", forceLink(graphData.links).distance(linkDistance)) .force("link", forceLink(graphData.links).distance(linkDistance))
.force("collide", forceCollide<NodeData>((n) => nodeRadius(n)).iterations(3)) .force("collide", forceCollide<NodeData>((n) => nodeRadius(n)).iterations(3))
const width = graph.offsetWidth if (enableRadial)
const height = Math.max(graph.offsetHeight, 250) 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 // precompute style prop strings as pixi doesn't support css variables
const cssVars = [ const cssVars = [