Hylograph.Scene.Handle
- Package
- purescript-hylograph-simulation
- Repository
- afcondon/purescript-hylograph-simulation
Scene Handle
Opaque handle for scene-based visualizations. Wraps simulation + scene engine + transition state. User never sees Refs - just pure-looking Effect operations.
This is the high-level API for sophisticated visualizations with:
- Choreographed scene transitions (Init → Interpolate → Finalize)
- Node filtering (for focus/neighborhood views)
- GUP-style enter/exit animations
Example usage:
-- Create handle with callbacks
handle <- Scene.create config callbacks nodes links renderFn
-- Transition to a scene
Scene.transitionTo treeFormScene handle
-- In your animation loop
continuing <- Scene.onTick handle
when continuing $ requestAnimationFrame (const $ ...)
-- Clean up
Scene.destroy handle
#SceneHandle Source
newtype SceneHandle :: Row Type -> Row Type -> Typenewtype SceneHandle nodeRow linkRow
Opaque handle to a scene-based visualization.
User cannot access internal state directly. All operations go through the module's exported functions.
#HandleConfig Source
type HandleConfig = { containerSelector :: String, linksGroupId :: Maybe GroupId, nodesGroupId :: GroupId }Configuration for creating a handle
#Callbacks Source
type Callbacks :: Row Type -> Typetype Callbacks nodeRow = { onNodeClick :: SimulationNode nodeRow -> Effect Unit, onNodeHover :: SimulationNode nodeRow -> Effect Unit, onNodeLeave :: Effect Unit, onTransitionComplete :: Effect Unit }
Callbacks for events (D3 → User code)
These are called when D3 events fire. Use them to notify your UI framework (Halogen, React, etc.) of user interactions.
#create Source
create :: forall nodeRow linkRow. HandleConfig -> Callbacks nodeRow -> Array (SimulationNode nodeRow) -> Array { source :: Int, target :: Int | linkRow } -> (Array (SimulationNode nodeRow) -> Effect Unit) -> Effect (SceneHandle nodeRow linkRow)Create a new scene handle.
Sets up:
- D3 force simulation with the provided nodes/links
- Scene engine for managing transitions
- Event binding via callbacks
The render function is called on every tick with current node positions.
#destroy Source
destroy :: forall nodeRow linkRow. SceneHandle nodeRow linkRow -> Effect UnitClean up resources.
Stops the simulation and releases references.
#transitionTo Source
transitionTo :: forall nodeRow linkRow. SceneConfig (SimulationNode nodeRow) -> SceneHandle nodeRow linkRow -> Effect UnitTransition to a new scene.
Triggers the three-phase lifecycle:
- Init rules - prepare starting state (e.g., move nodes to root)
- Interpolation - animate positions from start to target
- Final rules - set up stable state (e.g., pin/unpin nodes)
The transition is driven by onTick calls.
#isTransitioning Source
isTransitioning :: forall nodeRow linkRow. SceneHandle nodeRow linkRow -> Effect BooleanCheck if a transition is currently in progress.
#getTransitionProgress Source
getTransitionProgress :: forall nodeRow linkRow. SceneHandle nodeRow linkRow -> Effect (Maybe Number)Get transition progress (0.0 to 1.0).
Returns Nothing if no transition is in progress.
#getCurrentScene Source
getCurrentScene :: forall nodeRow linkRow. SceneHandle nodeRow linkRow -> Effect (Maybe (SceneConfig (SimulationNode nodeRow)))Get the current scene configuration (if any).
#getAllNodes Source
getAllNodes :: forall nodeRow linkRow. SceneHandle nodeRow linkRow -> Effect (Array (SimulationNode nodeRow))Get all nodes (with current positions).
#filterNodes Source
filterNodes :: forall nodeRow linkRow. (SimulationNode nodeRow -> Boolean) -> SceneHandle nodeRow linkRow -> Effect UnitFilter visible nodes by predicate.
Nodes that don't match are hidden (but kept in simulation).
Use showAllNodes to restore.
This is useful for neighborhood/focus views.
#showAllNodes Source
showAllNodes :: forall nodeRow linkRow. SceneHandle nodeRow linkRow -> Effect UnitShow all nodes (restore from filter).
#transformNodes Source
transformNodes :: forall nodeRow linkRow. (SimulationNode nodeRow -> SimulationNode nodeRow) -> SceneHandle nodeRow linkRow -> Effect UnitTransform nodes in place.
Applies a function to all nodes, mutating them directly. Useful for setting fx/fy (pinning) or updating positions.
After transformation, forces are re-initialized and simulation reheated.
#onTick Source
onTick :: forall nodeRow linkRow. SceneHandle nodeRow linkRow -> Effect BooleanTick handler - call this from your animation loop.
Advances interpolation during transitions, then calls the render function.
Returns true if animation should continue, false if stable.
Typical usage:
let loop = do
continuing <- Scene.onTick handle
when continuing $ requestAnimationFrame (const loop)
loop
#getSimulation Source
getSimulation :: forall nodeRow linkRow. SceneHandle nodeRow linkRow -> Effect (Simulation nodeRow linkRow)Get the underlying simulation (for advanced use cases).
Use with caution - direct manipulation may interfere with scene transitions.
#reheat Source
reheat :: forall nodeRow linkRow. SceneHandle nodeRow linkRow -> Effect UnitReheat the simulation manually.
Useful when you've made changes outside the normal transition flow.
Re-exports from Hylograph.Scene.Types
#SceneConfig Source
type SceneConfig node = { finalRules :: Array node -> Array (NodeRule node), initRules :: Array (NodeRule node), layout :: Array node -> PositionMap, name :: String, stableMode :: EngineMode }Scene configuration with three-phase lifecycle.
Phase 1: Initialize (initRules)
Applied before transition starts. Use this to set up starting positions,
e.g., moving tree nodes to the root for a "grow from root" animation.
Phase 2: Transition (layout)
The interpolation engine smoothly moves nodes from their current positions
to the target positions computed by the layout function.
Phase 3: Finalize (finalRules)
Applied after transition completes. Use this to set up the stable state,
e.g., unpinning nodes so forces can take over, or setting gridX/gridY.
Example:
treeFormScene :: SceneConfig MyNode
treeFormScene =
{ name: "TreeForm"
, initRules: [ moveToRootRule ]
, layout: \nodes -> computeTreePositions nodes
, finalRules: \_ -> [ pinAtTreePositionsRule ]
, stableMode: Static
}
#PositionMap Source
type PositionMap = Object PositionPosition map: node ID (as string) -> position Used for capturing current positions and specifying targets
#NodeRule Source
type NodeRule node = { apply :: node -> node, name :: String, select :: node -> Boolean }A rule that selects nodes and applies a transform.
Rules are applied with first-match-wins semantics (like CSS cascade). If multiple rules match a node, only the first one applies.
Example:
pinPackages :: NodeRule MyNode
pinPackages =
{ name: "pinPackages"
, select: \n -> n.nodeType == Package
, apply: \n -> n { fx = notNull n.x, fy = notNull n.y }
}
#EngineMode Source
data EngineModeEngine mode determines what happens after a transition completes.
Physics: D3 force simulation runs, nodes settle via forcesStatic: Nodes stay pinned at their final positions
Constructors
Instances
- Modules
- Hylograph.
Config. Apply - Hylograph.
Config. Force - Hylograph.
Config. Scene - Hylograph.
ForceEngine - Hylograph.
ForceEngine. Core - Hylograph.
ForceEngine. Demo - Hylograph.
ForceEngine. Events - Hylograph.
ForceEngine. Links - Hylograph.
ForceEngine. Registry - Hylograph.
ForceEngine. Render - Hylograph.
ForceEngine. Setup - Hylograph.
ForceEngine. Setup. WASM - Hylograph.
ForceEngine. Simulation - Hylograph.
ForceEngine. Types - Hylograph.
ForceEngine. WASM - Hylograph.
ForceEngine. WASMEngine - Hylograph.
Scene. Engine - Hylograph.
Scene. Handle - Hylograph.
Scene. Rules - Hylograph.
Scene. Types - Hylograph.
Simulation - Hylograph.
Simulation. Emitter - Hylograph.
Simulation. HATS - Hylograph.
Simulation. Scene - Hylograph.
Transition. Consumers - Hylograph.
Transition. Example