Grpah visualization implementation using egui
The project is close to the first stable version.
Currently not optimized for large graphs. The goal is to match egui drawing speed. Further optimizations are unnecessary.
The goal is to create a crate that expands egui's visualization capabilities and offers an easy-to-integrate, customizable graph visualization widget.
done -------------------------------------+---- basic graph drawing | [x] self-references, multi-connections | [x] zoom & pan, fit-to-screen | [x] drag node | [x] select, multiselect. | [x] style customizations | [ ] support egui dark/light theme | [ ] interactions vs egui draw benchmarks | [ ] documentation, tests, example | [ ]
First, let's define the ExampleApp
struct that will hold the graph elements and settings. The struct contains two fields: elements
and settings
. The elements field stores the graph's nodes and edges, while settings contains the configuration options for the GraphView widget.
rust
pub struct ExampleApp {
elements: Elements,
settings: Settings,
}
Next, implement the new()
function for the ExampleApp
struct. This function initializes the graph settings with default values and generates the graph elements.
rust
impl ExampleApp {
fn new(_: &CreationContext<'_>) -> Self {
let settings = Settings::default();
let elements = generate_graph();
Self { settings, elements }
}
}
Create a helper function called generate_graph()
that initializes the nodes and edges for the graph. In this example, we create three nodes with unique positions and three edges connecting them in a triangular pattern.
```rust
fn generate_graph() -> Elements {
let mut nodes = HashMap::new();
nodes.insert(0, Node::new(egui::Vec2::new(0., 30.)));
nodes.insert(1, Node::new(egui::Vec2::new(-30., 0.)));
nodes.insert(2, Node::new(egui::Vec2::new(30., 0.)));
let mut edges = HashMap::new();
edges.insert((0, 1), vec![Edge::new(0, 1, 0)]);
edges.insert((1, 2), vec![Edge::new(1, 2, 0)]);
edges.insert((2, 0), vec![Edge::new(2, 0, 0)]);
Elements::new(nodes, edges)
} ```
Now, implement the update()
function for the ExampleApp
. This function creates a GraphView
widget with the elements
and settings
, and adds it to the central panel using the ui.add()
function.
rust
impl App for ExampleApp {
fn update(&mut self, ctx: &Context, _: &mut eframe::Frame) {
let widget = &GraphView::new(&self.elements, &self.settings);
egui::CentralPanel::default().show(ctx, |ui| {
ui.add(widget);
});
}
}
Finally, run the application using the run_native()
function with the specified native options and the ExampleApp
.
rust
fn main() {
let native_options = eframe::NativeOptions::default();
run_native(
"egui_graphs_basic_demo",
native_options,
Box::new(|cc| Box::new(ExampleApp::new(cc))),
)
.unwrap();
}
You can further customize the appearance and behavior of your graph by modifying the settings or adding more nodes and edges as needed. Don't forget to apply changes returned from the widget.
You can check more advanced interactive example for usage references, settings description and changes apply demonstration.