Layout helpers.
- Server-side layouts written in Elixir:
tree/2(layered, like dagre or d3-hierarchy),force/2(force-directed, like d3-force) andresolve_collisions/2. They return%{node_id => %{x: x, y: y}}, which can be applied withapply_positions/2or animated withLiveFlow.animate_positions/5. prepare_layout_data/2/prepare_tree_layout_data/2send data to the client-side engines (ELK and the JS tree layout). ELK is optional and not bundled: add it withmix live_flow.gen.elk.
Layouts work on top-level nodes by default (child nodes keep their
position relative to their parent). Pass nodes: ids to restrict them.
Summary
Functions
Applies a %{id => %{x, y}} map (or list of {id, position}) to the flow.
Force-directed layout (Fruchterman-Reingold), similar to d3-force.
Prepares serializable layout data from the current flow state.
Prepares serializable layout data for the client-side tree layout algorithm.
Moves overlapping nodes apart (siblings only: child nodes are compared with the other children of the same parent).
Layered layout for trees and DAGs (similar to dagre / d3-hierarchy).
Functions
@spec apply_positions(LiveFlow.State.t(), map() | list()) :: LiveFlow.State.t()
Applies a %{id => %{x, y}} map (or list of {id, position}) to the flow.
@spec force( LiveFlow.State.t(), keyword() ) :: %{required(String.t()) => %{x: float(), y: float()}}
Force-directed layout (Fruchterman-Reingold), similar to d3-force.
Starts from the current positions and is deterministic.
Options
:iterations- Simulation steps (default:300):distance- Ideal edge length (default:200):fixed- Node IDs that keep their position (default:[]):nodes- Only lay out these node IDs (default: top-level nodes)
@spec prepare_layout_data(LiveFlow.State.t(), map()) :: map()
Prepares serializable layout data from the current flow state.
Returns a map with nodes (list of id/width/height maps) and
edges (list of id/source/target maps) suitable for sending
to the client-side ELK layout engine via push_event. The app must
register ELK first (mix live_flow.gen.elk).
Options (string keys, e.g. straight from event params)
"direction"-"DOWN","RIGHT","UP"or"LEFT"(default:"DOWN")"options"- Extra ELK layout options, e.g.%{"elk.algorithm" => "mrtree"}"flow_id"- Only the flow with this DOM id runs the layout
Examples
push_event(socket, "lf:layout_data", Layout.prepare_layout_data(flow, %{"direction" => "RIGHT"}))
@spec prepare_tree_layout_data(LiveFlow.State.t(), map()) :: map()
Prepares serializable layout data for the client-side tree layout algorithm.
Similar to prepare_layout_data/2 but outputs options compatible with
the pure JS tree layout engine (direction: TB/LR, nodeSpacing, levelSpacing).
Push it as lf:tree_layout_data; no ELK needed.
Options (string keys)
"direction"-"TB"or"LR"(default:"TB")"flow_id"- Only the flow with this DOM id runs the layout
@spec resolve_collisions( LiveFlow.State.t(), keyword() ) :: %{required(String.t()) => %{x: float(), y: float()}}
Moves overlapping nodes apart (siblings only: child nodes are compared with the other children of the same parent).
Returns the new positions of the nodes that moved.
Options
:margin- Minimum gap between nodes (default:10):max_iterations- (default:50):fixed- Node IDs that never move, e.g. the node just dropped (default:[])
@spec tree( LiveFlow.State.t(), keyword() ) :: %{required(String.t()) => %{x: float(), y: float()}}
Layered layout for trees and DAGs (similar to dagre / d3-hierarchy).
Nodes are ranked by their longest path from a root, ordered inside each rank to reduce crossings, and placed close to the center of their parents.
Options
:direction-:tb(top to bottom) or:lr(left to right) (default::tb):node_spacing- Space between nodes of the same rank (default:40):rank_spacing- Space between ranks (default:80):nodes- Only lay out these node IDs (default: top-level nodes):origin-{x, y}of the top-left corner (default:{0, 0})