mirror of
https://github.com/emilk/egui.git
synced 2026-06-27 15:13:12 -04:00
Plot custom zoom (#2714)
<!-- Please read the "Making a PR" section of [`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/master/CONTRIBUTING.md) before opening a Pull Request! * Keep your PR:s small and focused. * If applicable, add a screenshot or gif. * Unless this is a trivial change, add a line to the relevant `CHANGELOG.md` under "Unreleased". * If it is a non-trivial addition, consider adding a demo for it to `egui_demo_lib`. * Remember to run `cargo fmt` and `cargo clippy`. * Open the PR as a draft until you have self-reviewed it and run `./sh/check.sh`. * When you have addressed a PR comment, mark it as resolved. Please be patient! I will review you PR, but my time is limited! --> - Added methods to zoom the plot programmatically, to match the previously added `translate_bounds()`. - Added an example of how this method can be used to customize the plot navigation. Closes #1164.
This commit is contained in:
@@ -1002,6 +1002,10 @@ impl Plot {
|
||||
auto_bounds = false.into();
|
||||
}
|
||||
BoundsModification::AutoBounds(new_auto_bounds) => auto_bounds = new_auto_bounds,
|
||||
BoundsModification::Zoom(zoom_factor, center) => {
|
||||
bounds.zoom(zoom_factor, center);
|
||||
auto_bounds = false.into();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1341,6 +1345,7 @@ enum BoundsModification {
|
||||
Set(PlotBounds),
|
||||
Translate(Vec2),
|
||||
AutoBounds(Vec2b),
|
||||
Zoom(Vec2, PlotPoint),
|
||||
}
|
||||
|
||||
/// Provides methods to interact with a plot while building it. It is the single argument of the closure
|
||||
@@ -1404,6 +1409,31 @@ impl PlotUi {
|
||||
&self.response
|
||||
}
|
||||
|
||||
/// Scale the plot bounds around a position in screen coordinates.
|
||||
///
|
||||
/// Can be useful for implementing alternative plot navigation methods.
|
||||
///
|
||||
/// The plot bounds are divided by `zoom_factor`, therefore:
|
||||
/// - `zoom_factor < 1.0` zooms out, i.e., increases the visible range to show more data.
|
||||
/// - `zoom_factor > 1.0` zooms in, i.e., reduces the visible range to show more detail.
|
||||
pub fn zoom_bounds(&mut self, zoom_factor: Vec2, center: PlotPoint) {
|
||||
self.bounds_modifications
|
||||
.push(BoundsModification::Zoom(zoom_factor, center));
|
||||
}
|
||||
|
||||
/// Scale the plot bounds around the hovered position, if any.
|
||||
///
|
||||
/// Can be useful for implementing alternative plot navigation methods.
|
||||
///
|
||||
/// The plot bounds are divided by `zoom_factor`, therefore:
|
||||
/// - `zoom_factor < 1.0` zooms out, i.e., increases the visible range to show more data.
|
||||
/// - `zoom_factor > 1.0` zooms in, i.e., reduces the visible range to show more detail.
|
||||
pub fn zoom_bounds_around_hovered(&mut self, zoom_factor: Vec2) {
|
||||
if let Some(hover_pos) = self.pointer_coordinate() {
|
||||
self.zoom_bounds(zoom_factor, hover_pos);
|
||||
}
|
||||
}
|
||||
|
||||
/// The pointer position in plot coordinates. Independent of whether the pointer is in the plot area.
|
||||
pub fn pointer_coordinate(&self) -> Option<PlotPoint> {
|
||||
// We need to subtract the drag delta to keep in sync with the frame-delayed screen transform:
|
||||
|
||||
@@ -150,6 +150,13 @@ impl PlotBounds {
|
||||
self.translate_y(delta.y as f64);
|
||||
}
|
||||
|
||||
pub(crate) fn zoom(&mut self, zoom_factor: Vec2, center: PlotPoint) {
|
||||
self.min[0] = center.x + (self.min[0] - center.x) / (zoom_factor.x as f64);
|
||||
self.max[0] = center.x + (self.max[0] - center.x) / (zoom_factor.x as f64);
|
||||
self.min[1] = center.y + (self.min[1] - center.y) / (zoom_factor.y as f64);
|
||||
self.max[1] = center.y + (self.max[1] - center.y) / (zoom_factor.y as f64);
|
||||
}
|
||||
|
||||
pub(crate) fn add_relative_margin_x(&mut self, margin_fraction: Vec2) {
|
||||
let width = self.width().max(0.0);
|
||||
self.expand_x(margin_fraction.x as f64 * width);
|
||||
@@ -255,10 +262,7 @@ impl PlotTransform {
|
||||
let center = self.value_from_position(center);
|
||||
|
||||
let mut new_bounds = self.bounds;
|
||||
new_bounds.min[0] = center.x + (new_bounds.min[0] - center.x) / (zoom_factor.x as f64);
|
||||
new_bounds.max[0] = center.x + (new_bounds.max[0] - center.x) / (zoom_factor.x as f64);
|
||||
new_bounds.min[1] = center.y + (new_bounds.min[1] - center.y) / (zoom_factor.y as f64);
|
||||
new_bounds.max[1] = center.y + (new_bounds.max[1] - center.y) / (zoom_factor.y as f64);
|
||||
new_bounds.zoom(zoom_factor, center);
|
||||
|
||||
if new_bounds.is_valid() {
|
||||
self.bounds = new_bounds;
|
||||
|
||||
Reference in New Issue
Block a user