mirror of
https://github.com/emilk/egui.git
synced 2026-06-26 22:53:14 -04:00
Move egui_plot to its own repo (#4828)
* Part of https://github.com/emilk/egui/issues/4705 `egui_plot` can now be found at https://github.com/emilk/egui_plot
This commit is contained in:
@@ -1,23 +0,0 @@
|
||||
[package]
|
||||
name = "custom_plot_manipulation"
|
||||
version = "0.1.0"
|
||||
authors = ["Ygor Souza <ygor.souza@protonmail.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.76"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
|
||||
[dependencies]
|
||||
eframe = { workspace = true, features = [
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
egui_plot.workspace = true
|
||||
env_logger = { version = "0.10", default-features = false, features = [
|
||||
"auto-color",
|
||||
"humantime",
|
||||
] }
|
||||
@@ -1,7 +0,0 @@
|
||||
Example how to use raw input events to implement alternative controls to pan and zoom the plot
|
||||
|
||||
```sh
|
||||
cargo run -p custom_plot_manipulation
|
||||
```
|
||||
|
||||

|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 39 KiB |
@@ -1,129 +0,0 @@
|
||||
//! This example shows how to implement custom gestures to pan and zoom in the plot
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||
#![allow(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
|
||||
use eframe::egui::{self, DragValue, Event, Vec2};
|
||||
use egui_plot::{Legend, Line, PlotPoints};
|
||||
|
||||
fn main() -> eframe::Result {
|
||||
env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`).
|
||||
let options = eframe::NativeOptions::default();
|
||||
eframe::run_native(
|
||||
"Plot",
|
||||
options,
|
||||
Box::new(|_cc| Ok(Box::<PlotExample>::default())),
|
||||
)
|
||||
}
|
||||
|
||||
struct PlotExample {
|
||||
lock_x: bool,
|
||||
lock_y: bool,
|
||||
ctrl_to_zoom: bool,
|
||||
shift_to_horizontal: bool,
|
||||
zoom_speed: f32,
|
||||
scroll_speed: f32,
|
||||
}
|
||||
|
||||
impl Default for PlotExample {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
lock_x: false,
|
||||
lock_y: false,
|
||||
ctrl_to_zoom: false,
|
||||
shift_to_horizontal: false,
|
||||
zoom_speed: 1.0,
|
||||
scroll_speed: 1.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl eframe::App for PlotExample {
|
||||
fn update(&mut self, ctx: &egui::Context, _: &mut eframe::Frame) {
|
||||
egui::SidePanel::left("options").show(ctx, |ui| {
|
||||
ui.checkbox(&mut self.lock_x, "Lock x axis").on_hover_text("Check to keep the X axis fixed, i.e., pan and zoom will only affect the Y axis");
|
||||
ui.checkbox(&mut self.lock_y, "Lock y axis").on_hover_text("Check to keep the Y axis fixed, i.e., pan and zoom will only affect the X axis");
|
||||
ui.checkbox(&mut self.ctrl_to_zoom, "Ctrl to zoom").on_hover_text("If unchecked, the behavior of the Ctrl key is inverted compared to the default controls\ni.e., scrolling the mouse without pressing any keys zooms the plot");
|
||||
ui.checkbox(&mut self.shift_to_horizontal, "Shift for horizontal scroll").on_hover_text("If unchecked, the behavior of the shift key is inverted compared to the default controls\ni.e., hold to scroll vertically, release to scroll horizontally");
|
||||
ui.horizontal(|ui| {
|
||||
ui.add(
|
||||
DragValue::new(&mut self.zoom_speed)
|
||||
.range(0.1..=2.0)
|
||||
.speed(0.1),
|
||||
);
|
||||
ui.label("Zoom speed").on_hover_text("How fast to zoom in and out with the mouse wheel");
|
||||
});
|
||||
ui.horizontal(|ui| {
|
||||
ui.add(
|
||||
DragValue::new(&mut self.scroll_speed)
|
||||
.range(0.1..=100.0)
|
||||
.speed(0.1),
|
||||
);
|
||||
ui.label("Scroll speed").on_hover_text("How fast to pan with the mouse wheel");
|
||||
});
|
||||
});
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
let (scroll, pointer_down, modifiers) = ui.input(|i| {
|
||||
let scroll = i.events.iter().find_map(|e| match e {
|
||||
Event::MouseWheel {
|
||||
unit: _,
|
||||
delta,
|
||||
modifiers: _,
|
||||
} => Some(*delta),
|
||||
_ => None,
|
||||
});
|
||||
(scroll, i.pointer.primary_down(), i.modifiers)
|
||||
});
|
||||
|
||||
ui.label("This example shows how to use raw input events to implement different plot controls than the ones egui provides by default, e.g., default to zooming instead of panning when the Ctrl key is not pressed, or controlling much it zooms with each mouse wheel step.");
|
||||
|
||||
egui_plot::Plot::new("plot")
|
||||
.allow_zoom(false)
|
||||
.allow_drag(false)
|
||||
.allow_scroll(false)
|
||||
.legend(Legend::default())
|
||||
.show(ui, |plot_ui| {
|
||||
if let Some(mut scroll) = scroll {
|
||||
if modifiers.ctrl == self.ctrl_to_zoom {
|
||||
scroll = Vec2::splat(scroll.x + scroll.y);
|
||||
let mut zoom_factor = Vec2::from([
|
||||
(scroll.x * self.zoom_speed / 10.0).exp(),
|
||||
(scroll.y * self.zoom_speed / 10.0).exp(),
|
||||
]);
|
||||
if self.lock_x {
|
||||
zoom_factor.x = 1.0;
|
||||
}
|
||||
if self.lock_y {
|
||||
zoom_factor.y = 1.0;
|
||||
}
|
||||
plot_ui.zoom_bounds_around_hovered(zoom_factor);
|
||||
} else {
|
||||
if modifiers.shift == self.shift_to_horizontal {
|
||||
scroll = Vec2::new(scroll.y, scroll.x);
|
||||
}
|
||||
if self.lock_x {
|
||||
scroll.x = 0.0;
|
||||
}
|
||||
if self.lock_y {
|
||||
scroll.y = 0.0;
|
||||
}
|
||||
let delta_pos = self.scroll_speed * scroll;
|
||||
plot_ui.translate_bounds(delta_pos);
|
||||
}
|
||||
}
|
||||
if plot_ui.response().hovered() && pointer_down {
|
||||
let mut pointer_translate = -plot_ui.pointer_coordinate_drag_delta();
|
||||
if self.lock_x {
|
||||
pointer_translate.x = 0.0;
|
||||
}
|
||||
if self.lock_y {
|
||||
pointer_translate.y = 0.0;
|
||||
}
|
||||
plot_ui.translate_bounds(pointer_translate);
|
||||
}
|
||||
|
||||
let sine_points = PlotPoints::from_explicit_callback(|x| x.sin(), .., 5000);
|
||||
plot_ui.line(Line::new(sine_points).name("Sine"));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
[package]
|
||||
name = "save_plot"
|
||||
version = "0.1.0"
|
||||
authors = ["hacknus <l_stoeckli@bluewin.ch>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.76"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
eframe = { workspace = true, features = [
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
egui_plot.workspace = true
|
||||
image = { workspace = true, features = ["png"] }
|
||||
rfd = "0.13.0"
|
||||
env_logger = { version = "0.10", default-features = false, features = [
|
||||
"auto-color",
|
||||
"humantime",
|
||||
] }
|
||||
@@ -1,7 +0,0 @@
|
||||
This example shows that you can save a plot in egui as a png.
|
||||
|
||||
```sh
|
||||
cargo run -p save_plot
|
||||
```
|
||||
|
||||

|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 6.3 KiB |
@@ -1,75 +0,0 @@
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||
#![allow(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
|
||||
use eframe::egui;
|
||||
use egui_plot::{Legend, Line, Plot, PlotPoints};
|
||||
|
||||
fn main() -> eframe::Result {
|
||||
env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`).
|
||||
|
||||
let options = eframe::NativeOptions {
|
||||
viewport: egui::ViewportBuilder::default().with_inner_size([350.0, 200.0]),
|
||||
..Default::default()
|
||||
};
|
||||
eframe::run_native(
|
||||
"My egui App with a plot",
|
||||
options,
|
||||
Box::new(|_cc| Ok(Box::<MyApp>::default())),
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct MyApp {}
|
||||
|
||||
impl eframe::App for MyApp {
|
||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||
let mut plot_rect = None;
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
if ui.button("Save Plot").clicked() {
|
||||
ctx.send_viewport_cmd(egui::ViewportCommand::Screenshot);
|
||||
}
|
||||
|
||||
let my_plot = Plot::new("My Plot").legend(Legend::default());
|
||||
|
||||
// let's create a dummy line in the plot
|
||||
let graph: Vec<[f64; 2]> = vec![[0.0, 1.0], [2.0, 3.0], [3.0, 2.0]];
|
||||
let inner = my_plot.show(ui, |plot_ui| {
|
||||
plot_ui.line(Line::new(PlotPoints::from(graph)).name("curve"));
|
||||
});
|
||||
// Remember the position of the plot
|
||||
plot_rect = Some(inner.response.rect);
|
||||
});
|
||||
|
||||
// Check for returned screenshot:
|
||||
let screenshot = ctx.input(|i| {
|
||||
for event in &i.raw.events {
|
||||
if let egui::Event::Screenshot { image, .. } = event {
|
||||
return Some(image.clone());
|
||||
}
|
||||
}
|
||||
None
|
||||
});
|
||||
|
||||
if let (Some(screenshot), Some(plot_location)) = (screenshot, plot_rect) {
|
||||
if let Some(mut path) = rfd::FileDialog::new().save_file() {
|
||||
path.set_extension("png");
|
||||
|
||||
// for a full size application, we should put this in a different thread,
|
||||
// so that the GUI doesn't lag during saving
|
||||
|
||||
let pixels_per_point = ctx.pixels_per_point();
|
||||
let plot = screenshot.region(&plot_location, Some(pixels_per_point));
|
||||
// save the plot to png
|
||||
image::save_buffer(
|
||||
&path,
|
||||
plot.as_raw(),
|
||||
plot.width() as u32,
|
||||
plot.height() as u32,
|
||||
image::ColorType::Rgba8,
|
||||
)
|
||||
.unwrap();
|
||||
eprintln!("Image saved to {path:?}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user