fix(spa): only render graph once in global

Signed-off-by: Aaron Pham <contact@aarnphm.xyz>
This commit is contained in:
Aaron Pham 2024-08-15 04:16:42 -04:00
parent dd4b1cd604
commit b88be2f767
No known key found for this signature in database
GPG Key ID: 18974753009D2BFA
2 changed files with 29 additions and 14 deletions

View File

@ -64,7 +64,7 @@ export default ((opts?: GraphOptions) => {
<div class={classNames(displayClass, "graph")}> <div class={classNames(displayClass, "graph")}>
<h3>{i18n(cfg.locale).components.graph.title}</h3> <h3>{i18n(cfg.locale).components.graph.title}</h3>
<div class="graph-outer"> <div class="graph-outer">
<canvas id="graph-container" data-cfg={JSON.stringify(localGraph)}></canvas> <div id="graph-container" data-cfg={JSON.stringify(localGraph)}></div>
<svg <svg
version="1.1" version="1.1"
id="global-graph-icon" id="global-graph-icon"

View File

@ -2,7 +2,7 @@ import type { ContentDetails } from "../../plugins/emitters/contentIndex"
import * as d3 from "d3" import * as d3 from "d3"
import * as PIXI from "pixi.js" import * as PIXI from "pixi.js"
import * as TWEEN from "@tweenjs/tween.js" import * as TWEEN from "@tweenjs/tween.js"
import { registerEscapeHandler } from "./util" import { registerEscapeHandler, removeAllChildren } from "./util"
import { FullSlug, SimpleSlug, getFullSlug, resolveRelative, simplifySlug } from "../../util/path" import { FullSlug, SimpleSlug, getFullSlug, resolveRelative, simplifySlug } from "../../util/path"
type NodeData = { type NodeData = {
@ -58,12 +58,16 @@ function animate(time: number) {
} }
requestAnimationFrame(animate) requestAnimationFrame(animate)
async function renderGraph(container: string, fullSlug: FullSlug) { async function renderGraph(container: string, fullSlug: FullSlug, global?: boolean) {
const canvas = document.getElementById(container) as HTMLCanvasElement | null
if (!canvas) return
const slug = simplifySlug(fullSlug) const slug = simplifySlug(fullSlug)
const visited = getVisited() const visited = getVisited()
const graph = document.getElementById(container)
if (!graph) return
global = global ?? false
if (!global) {
removeAllChildren(graph)
}
let { let {
drag: enableDrag, drag: enableDrag,
@ -78,7 +82,7 @@ async function renderGraph(container: string, fullSlug: FullSlug) {
removeTags, removeTags,
showTags, showTags,
focusOnHover, focusOnHover,
} = JSON.parse(canvas.dataset["cfg"]!) } = JSON.parse(graph.dataset["cfg"]!)
const data: Map<SimpleSlug, ContentDetails> = new Map( const data: Map<SimpleSlug, ContentDetails> = new Map(
Object.entries<ContentDetails>(await fetchData).map(([k, v]) => [ Object.entries<ContentDetails>(await fetchData).map(([k, v]) => [
@ -133,8 +137,6 @@ async function renderGraph(container: string, fullSlug: FullSlug) {
if (showTags) tags.forEach((tag) => neighbourhood.add(tag)) if (showTags) tags.forEach((tag) => neighbourhood.add(tag))
} }
// XXX: How does links got morphed into LinkNodes here?
// links => LinkData[], where as links.filter(l => neighbourhood.has(l.source) && neighbourhood.has(l.target)) => LinkNodes[]
const graphData: { nodes: NodeData[]; links: LinkNodes[] } = { const graphData: { nodes: NodeData[]; links: LinkNodes[] } = {
nodes: [...neighbourhood].map((url) => { nodes: [...neighbourhood].map((url) => {
const text = url.startsWith("tags/") ? "#" + url.substring(5) : (data.get(url)?.title ?? url) const text = url.startsWith("tags/") ? "#" + url.substring(5) : (data.get(url)?.title ?? url)
@ -165,8 +167,8 @@ async function renderGraph(container: string, fullSlug: FullSlug) {
d3.forceCollide((n) => nodeRadius(n)), d3.forceCollide((n) => nodeRadius(n)),
) )
const width = canvas.offsetWidth const width = graph.offsetWidth
const height = Math.max(canvas.offsetHeight, 250) const height = Math.max(graph.offsetHeight, 250)
const computedStyleMap = new Map<string, string>() const computedStyleMap = new Map<string, string>()
for (let i of [ for (let i of [
"--secondary", "--secondary",
@ -178,7 +180,7 @@ async function renderGraph(container: string, fullSlug: FullSlug) {
"--darkgray", "--darkgray",
"--bodyFont", "--bodyFont",
]) { ]) {
computedStyleMap.set(i, getComputedStyle(canvas).getPropertyValue(i)) computedStyleMap.set(i, getComputedStyle(graph).getPropertyValue(i))
} }
// calculate color // calculate color
@ -304,7 +306,7 @@ async function renderGraph(container: string, fullSlug: FullSlug) {
await app.init({ await app.init({
width, width,
height, height,
canvas: canvas, canvas: global ? (graph as HTMLCanvasElement) : undefined,
antialias: true, antialias: true,
autoStart: false, autoStart: false,
autoDensity: true, autoDensity: true,
@ -314,6 +316,10 @@ async function renderGraph(container: string, fullSlug: FullSlug) {
eventMode: "static", eventMode: "static",
}) })
if (!global) {
graph.appendChild(app.canvas)
}
const stage = app.stage const stage = app.stage
stage.interactive = false stage.interactive = false
@ -454,7 +460,16 @@ async function renderGraph(container: string, fullSlug: FullSlug) {
} }
}), }),
) )
} else {
graphData.nodes.forEach((node) => {
if (!node.gfx) return
node.gfx.on("click", () => {
const targ = resolveRelative(fullSlug, node.id)
window.spaNavigate(new URL(targ, window.location.toString()))
})
})
} }
if (enableZoom) { if (enableZoom) {
d3.select<HTMLCanvasElement, NodeData>(app.canvas).call( d3.select<HTMLCanvasElement, NodeData>(app.canvas).call(
d3 d3
@ -520,7 +535,7 @@ document.addEventListener("nav", async (e: CustomEventMap["nav"]) => {
sidebar.style.zIndex = "1" sidebar.style.zIndex = "1"
} }
renderGraph("global-graph-container", slug) renderGraph("global-graph-container", slug, true)
registerEscapeHandler(container, hideGlobalGraph) registerEscapeHandler(container, hideGlobalGraph)
} }