Nodes are ordinary iced widgets - sliders, text inputs, whatever your view
builds - placed on an infinite zoom/pan canvas and wired together through typed
pins. The widget holds no graph state: your application owns the data model,
and connections, moves, and deletes arrive as messages, like any other iced
widget. Everything on the canvas is drawn by a single WGPU pipeline as signed
distance fields, so it stays sharp at every zoom level and handles graphs with
hundreds of nodes.
Getting started
use *;
use ;
use ;
node(..) and edge!(..) are builders: chain .style(..) for per-node and
per-edge looks, starting from presets like NodeStyle::input() or
EdgeStyle::error(). The crate docs cover
styling, connection validation, and the callback contract in detail.
Demos
Every demo runs natively and in the browser.
| Demo | Live | Shows |
|---|---|---|
hello_world |
run | Command palette, theme switching, selection, clone/delete, persistence |
styling |
run | Style presets and live node styling controls |
interaction |
run | Pin direction and type rules, connection validation, snap feedback |
500_nodes |
run | 500 nodes / 640 edges stress test with a runtime stats overlay |
shader_editor |
run | Visual WGSL editor: the graph compiles to a running shader |
Controls
| Action | Mouse / Keyboard | Touch |
|---|---|---|
| Pan | Right mouse drag | One-finger drag on empty canvas, or two-finger drag |
| Zoom | Scroll wheel (zooms at cursor) | Two-finger pinch |
| Connect | Drag from pin to pin | Drag from pin to pin |
| Disconnect | Click a connected pin to unplug | Tap a connected pin to unplug |
| Fork edge | Shift+drag from a connected pin | - |
| Move node | Drag node | Drag node |
| Box select | Left drag on empty canvas | - (empty-canvas drag pans) |
| Add to selection | Shift+click | - |
| Select all | Ctrl+A | - |
| Clone selection | Ctrl+D (web: Alt+D) | - |
| Delete selection | Delete / Backspace (web: Delete) | - |
| Cut edges | Ctrl+click an edge, or Ctrl+drag across edges | - |
Ctrl is Cmd on macOS. On the web, clone avoids Ctrl/Cmd+D (the browser's
bookmark shortcut) and delete drops the Backspace alternative (legacy
back-navigation). Every binding is host-rebindable through
NodeGraph::keymap - see the Keymap type. Connections snap while dragging
near a compatible pin - like plugging in a cable - rather than on mouse
release, and compatible targets pulse during the drag.
How it works
Your app owns the graph. The widget is stateless between frames: it renders
the nodes and edges you pass in and reports intent (on_connect, on_move,
on_delete, ...) through callbacks. Your update logic applies the change and
the next view reflects it - the plain iced loop, no hidden state to sync.
One GPU pipeline. Node bodies, edges, pins, shadows, and the background
grid are compiled into a single signed-distance-field scene and rendered by
the in-tree iced_nodegraph_sdf
crate. A compute-shader tile index culls per pixel, and animated stroke
patterns drive their own redraws. Details in
ARCHITECTURE.md.
Typed coordinates. Screen space and world space are distinct
euclid types, so mixing them up is a compile error.
Compatibility
- Targets iced 0.14 with the wgpu renderer (the SDF pipeline has no tiny-skia fallback).
- Native: Windows, macOS, Linux. Web: WebAssembly on WebGPU-capable browsers - there is no WebGL fallback, so Chrome/Chromium is recommended.
- Pre-1.0: minor releases may change the API. See the CHANGELOG.
Development
The workspace contains the widget (iced_nodegraph), the SDF renderer
(iced_nodegraph_sdf), and the demos.