Phase 5 (behavior-preserving): decompose the ~1000-line onMount into focused
modules coordinated by a plain (non-reactive) controller object:
- pixi/types.ts LineObject / NodeObject / BackgroundLayers
- pixi/controller.ts shared mutable pan/zoom state + Pixi refs (NOT $state,
which would break PixiJS object identity)
- pixi/background.ts gradient/nebula/stars/dust/vignette + ambient loops
- pixi/lines.ts plasma-beam connections
- pixi/nodes.ts origin + regular nodes; collapses the duplicated pointer
handlers into one attachNodeInteraction helper
- pixi/interaction.ts pan/zoom/parallax + keyboard nav (return cleanups)
- pixi/animation.ts sequenced entrance animation
onMount is now a thin orchestrator. SkillTree.svelte: 1177 -> 274 lines
(2453 at the start of the refactor). Listener passivity, the hasMoved click
guard, eventMode-until-animated ordering, and the R-reset parallax rebaseline
are all preserved.
svelte-check: 0 errors/0 warnings. lint/test/build clean. Verified onMount runs
with no runtime exceptions (background + stats panel render). NOTE: pan/zoom/
node-click/keyboard need a manual real-browser check (headless can't paint nodes).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
59 lines
1.5 KiB
TypeScript
59 lines
1.5 KiB
TypeScript
// Mutable controller object shared across the PixiJS modules.
|
|
//
|
|
// IMPORTANT: this must NOT be wrapped in Svelte's `$state` — the deep proxy
|
|
// breaks PixiJS's internal object identity checks. Keep it a plain object so
|
|
// the interaction, node, and animation modules can read/write the same
|
|
// mutable pan/zoom state by reference (the same single source of truth the
|
|
// original onMount closure relied on).
|
|
import type { Application, Container } from 'pixi.js';
|
|
import type { BackgroundLayers, LineObject, NodeObject } from './types';
|
|
|
|
export interface SkillTreeController {
|
|
app: Application;
|
|
treeContainer: Container;
|
|
bg: BackgroundLayers;
|
|
nodeObjects: NodeObject[];
|
|
lineObjects: LineObject[];
|
|
|
|
// Pan/zoom mutable state (was closure vars in onMount).
|
|
isDragging: boolean;
|
|
hasMoved: boolean;
|
|
dragStartX: number;
|
|
dragStartY: number;
|
|
containerStartX: number;
|
|
containerStartY: number;
|
|
lastTouchDistance: number;
|
|
isTouchZooming: boolean;
|
|
|
|
// Parallax baseline (re-set on view reset) + final zoom scale.
|
|
initialTreeX: number;
|
|
initialTreeY: number;
|
|
endScale: number;
|
|
}
|
|
|
|
export function createController(
|
|
app: Application,
|
|
treeContainer: Container,
|
|
bg: BackgroundLayers,
|
|
endScale: number
|
|
): SkillTreeController {
|
|
return {
|
|
app,
|
|
treeContainer,
|
|
bg,
|
|
nodeObjects: [],
|
|
lineObjects: [],
|
|
isDragging: false,
|
|
hasMoved: false,
|
|
dragStartX: 0,
|
|
dragStartY: 0,
|
|
containerStartX: 0,
|
|
containerStartY: 0,
|
|
lastTouchDistance: 0,
|
|
isTouchZooming: false,
|
|
initialTreeX: treeContainer.x,
|
|
initialTreeY: treeContainer.y,
|
|
endScale
|
|
};
|
|
}
|