Skip to main content

Crate egui_xyflow

Crate egui_xyflow 

Source
Expand description

§egui_xyflow

An interactive node-graph editor widget for egui, inspired by xyflow (React Flow / Svelte Flow). Supports drag-and-drop nodes, handle-to-handle edge connections, pan/zoom, multi-select, resize, minimap, edge labels, and an optional force-directed layout subsystem.

§Quick start

use eframe::egui;
use egui_xyflow::prelude::*;

struct MyApp {
    state: FlowState<String, ()>,
}

impl MyApp {
    fn new() -> Self {
        let mut state = FlowState::new(FlowConfig::default());

        state.add_node(
            Node::builder("1")
                .position(egui::pos2(100.0, 100.0))
                .data("Input".to_string())
                .handle(NodeHandle::source(Position::Right))
                .build(),
        );
        state.add_node(
            Node::builder("2")
                .position(egui::pos2(400.0, 100.0))
                .data("Output".to_string())
                .handle(NodeHandle::target(Position::Left))
                .build(),
        );
        state.add_edge(Edge::builder("e1-2", "1", "2").label("flow"));

        Self { state }
    }
}

impl eframe::App for MyApp {
    fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
        egui::CentralPanel::default().show(ctx, |ui| {
            let events =
                FlowCanvas::new(&mut self.state, &DefaultNodeWidget).show(ui);
            for conn in &events.connections_made {
                println!("new edge: {} -> {}", conn.source, conn.target);
            }
        });
    }
}

§Architecture

Every frame follows the same cycle:

FlowState  →  FlowCanvas::show()  →  FlowEvents  →  apply changes  →  FlowState
  1. FlowState owns the graph: nodes, edges, viewport, config, selection state.
  2. FlowCanvas renders the graph and processes input, returning FlowEvents that describe what happened this frame (clicks, drags, connections, selection changes, deletions, etc.).
  3. Most mutations are represented as NodeChange / EdgeChange enum variants and applied atomically via FlowState::apply_node_changes and FlowState::apply_edge_changes.

§Generic parameters

The library is parameterised over two user-owned types:

  • ND — custom data attached to each Node.
  • ED — custom data attached to each Edge.

Use () when you don’t need custom data, or String for simple labels, or a struct of your own.

§Coordinate spaces

Two coordinate systems convert via flow_to_screen and screen_to_flow using a Transform:

  • Flow space — graph coordinates you set on nodes. Unbounded.
  • Screen space — pixel coordinates inside the canvas rect.

§Render order

Bottom-to-top: background → edges (with optional viewport culling) → connection drag line → nodes (z-ordered) → handles → resize handles → selection rectangle → minimap.

§Customisation points

  • NodeWidget<D> — implement size() and show() for custom node rendering. Built-ins: DefaultNodeWidget (for Node<String>) and UnitNodeWidget (for Node<()>).
  • EdgeWidget<ED> — implement to render custom edge paths instead of the built-in EdgeType algorithms.
  • ConnectionValidator — reject prospective connections (e.g. no self-loops, typed handles).
  • FlowConfig — 60+ knobs for pan/zoom, selection, colour, edge defaults, handle appearance, grid snapping, animation, viewport culling, edge labels, etc.

§Physics (force-directed layout)

The physics module provides a D3-compatible force simulation usable alongside (or instead of) hand-placed node positions:

use egui_xyflow::physics::*;

let mut sim = ForceSimulation::from_state(&state)
    .add_force("charge",   ManyBodyForce::new().strength(-30.0))
    .add_force("links",    LinkForce::from_state(&state).distance(30.0))
    .add_force("position", PositionForce::new().strength(0.1))
    .add_force("center",   CenterForce::new());

// Each frame — `false` means the state was mutated, rebuild the sim.
if !sim.step(&mut state) {
    sim = ForceSimulation::from_state(&state);
}

The charge force uses a Barnes–Hut quadtree (θ = 0.9 by default), so it scales roughly O(n log n) with node count. physics is not re-exported from the prelude — import it explicitly.

§Feature flags

  • serde (default) — derive Serialize / Deserialize on FlowState, Node, Edge, and most config/viewport types. Disable for no-std-adjacent builds or to drop the serde dependency.

§Examples

The repository ships with 17 runnable examples:

cargo run --example basic_flow                   # getting started
cargo run --example edge_labels                  # labels + viewport culling
cargo run --example data_pipeline                # pipeline with validation
cargo run --example disjoint_force_graph         # physics: citation network
cargo run --release --example physics_bench      # physics timing harness

See the repo for the complete list.

§Compatibility

Built against egui 0.31. MSRV: 1.85 (edition 2024).

Re-exports§

pub use config::BackgroundVariant;
pub use config::FlowConfig;
pub use config::ZIndexMode;
pub use types::changes::EdgeChange;
pub use types::changes::NodeChange;
pub use types::connection::Connection;
pub use types::connection::ConnectionMode;
pub use types::connection::ConnectionState;
pub use types::connection::EdgeInfo;
pub use types::edge::AnchorEndpoint;
pub use types::edge::Edge;
pub use types::edge::EdgeAnchor;
pub use types::edge::EdgeGlow;
pub use types::edge::EdgeId;
pub use types::edge::EdgeMarker;
pub use types::edge::EdgePathResult;
pub use types::edge::EdgePosition;
pub use types::edge::EdgeStyle;
pub use types::edge::EdgeType;
pub use types::edge::MarkerType;
pub use types::handle::Handle;
pub use types::handle::HandleType;
pub use types::handle::NodeHandle;
pub use types::node::InternalNode;
pub use types::node::Node;
pub use types::node::NodeBuilder;
pub use types::node::NodeExtent;
pub use types::node::NodeHandleBounds;
pub use types::node::NodeId;
pub use types::node::NodeInternals;
pub use types::position::CoordinateExtent;
pub use types::position::Dimensions;
pub use types::position::NodeOrigin;
pub use types::position::Position;
pub use types::position::SnapGrid;
pub use types::position::Transform;
pub use types::viewport::PanOnScrollMode;
pub use types::viewport::SelectionMode;
pub use types::viewport::Viewport;
pub use state::flow_state::FlowState;
pub use events::FlowEvents;
pub use render::canvas::AllowAllConnections;
pub use render::canvas::ConnectionValidator;
pub use render::canvas::EdgeWidget;
pub use render::canvas::FlowCanvas;
pub use render::minimap::MinimapInfo;
pub use render::node_renderer::DefaultNodeWidget;
pub use render::node_renderer::NodeWidget;
pub use render::node_renderer::UnitNodeWidget;
pub use animation::easing;
pub use animation::viewport_animation::ViewportAnimation;
pub use state::node_lookup;
pub use graph::node_position::flow_to_screen;
pub use graph::node_position::screen_to_flow;
pub use graph::node_position::snap_position;
pub use graph::utils::get_connected_edges;
pub use graph::utils::get_incomers;
pub use graph::utils::get_nodes_bounds;
pub use graph::utils::get_outgoers;
pub use graph::utils::get_viewport_for_bounds;
pub use edges::bezier::get_bezier_path;
pub use edges::bezier::sample_bezier;
pub use edges::positions::get_edge_position;
pub use edges::positions::project_to_border;
pub use edges::smooth_step::get_smooth_step_path;
pub use edges::smooth_step::get_step_path;
pub use edges::straight::get_straight_path;
pub use interaction::resize::ResizeHandleKind;

Modules§

animation
Viewport animation with configurable easing functions.
config
Global configuration for the flow canvas.
edges
Edge path algorithms: Bezier, SmoothStep, Step, and Straight.
events
Per-frame event reporting for FlowCanvas.
graph
Graph utilities: coordinate transforms, bounds calculation, and neighbor queries.
interaction
Input handling: node dragging, pan/zoom, connection dragging, resize, and box selection.
physics
Force-directed physics simulation.
prelude
Convenience glob import that brings the most commonly needed items into scope.
render
Rendering subsystem: canvas orchestration, node/edge/handle/background renderers.
state
Graph state management: flow_state::FlowState, change application, and node lookup helpers.
types
Core data types for the flow graph.