Skip to content

Commit e031001

Browse files
committed
Allow x/y only zooming by click-dragging respective axis (#17)
1 parent 46b496c commit e031001

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed

demo/src/plot_demo.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -893,6 +893,7 @@ struct ChartsDemo {
893893
vertical: bool,
894894
allow_zoom: Vec2b,
895895
allow_drag: Vec2b,
896+
allow_axis_zoom_drag: Vec2b,
896897
allow_scroll: Vec2b,
897898
}
898899

@@ -903,6 +904,7 @@ impl Default for ChartsDemo {
903904
chart: Chart::default(),
904905
allow_zoom: true.into(),
905906
allow_drag: true.into(),
907+
allow_axis_zoom_drag: true.into(),
906908
allow_scroll: true.into(),
907909
}
908910
}
@@ -949,6 +951,12 @@ impl ChartsDemo {
949951
ui.checkbox(&mut self.allow_drag.x, "X");
950952
ui.checkbox(&mut self.allow_drag.y, "Y");
951953
});
954+
ui.horizontal(|ui| {
955+
ui.label("Allow axis zoom drag:");
956+
ui.checkbox(&mut self.allow_axis_zoom_drag.x, "X");
957+
ui.checkbox(&mut self.allow_axis_zoom_drag.y, "Y");
958+
});
959+
952960
ui.horizontal(|ui| {
953961
ui.label("Allow scroll:");
954962
ui.checkbox(&mut self.allow_scroll.x, "X");
@@ -987,6 +995,7 @@ impl ChartsDemo {
987995
.clamp_grid(true)
988996
.allow_zoom(self.allow_zoom)
989997
.allow_drag(self.allow_drag)
998+
.allow_axis_zoom_drag(self.allow_axis_zoom_drag)
990999
.allow_scroll(self.allow_scroll)
9911000
.show(ui, |plot_ui| plot_ui.bar_chart(chart))
9921001
.response

egui_plot/src/lib.rs

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ pub struct Plot<'a> {
156156
center_axis: Vec2b,
157157
allow_zoom: Vec2b,
158158
allow_drag: Vec2b,
159+
allow_axis_zoom_drag: Vec2b,
159160
allow_scroll: Vec2b,
160161
allow_double_click_reset: bool,
161162
allow_boxed_zoom: bool,
@@ -203,6 +204,7 @@ impl<'a> Plot<'a> {
203204
center_axis: false.into(),
204205
allow_zoom: true.into(),
205206
allow_drag: true.into(),
207+
allow_axis_zoom_drag: false.into(),
206208
allow_scroll: true.into(),
207209
allow_double_click_reset: true,
208210
allow_boxed_zoom: true,
@@ -388,6 +390,16 @@ impl<'a> Plot<'a> {
388390
self
389391
}
390392

393+
/// Whether to allow dragging in the axis areas to automaticall zoom the plot. Default: `true`.
394+
#[inline]
395+
pub fn allow_axis_zoom_drag<T>(mut self, on: T) -> Self
396+
where
397+
T: Into<Vec2b>,
398+
{
399+
self.allow_axis_zoom_drag = on.into();
400+
self
401+
}
402+
391403
/// Provide a function to customize the on-hover label for the x and y axis
392404
///
393405
/// ```
@@ -777,6 +789,7 @@ impl<'a> Plot<'a> {
777789
center_axis,
778790
allow_zoom,
779791
allow_drag,
792+
allow_axis_zoom_drag,
780793
allow_scroll,
781794
allow_double_click_reset,
782795
allow_boxed_zoom,
@@ -863,6 +876,31 @@ impl<'a> Plot<'a> {
863876
// Allocate the plot window.
864877
let response = ui.allocate_rect(plot_rect, sense);
865878

879+
let x_axis_responses = x_axis_widgets
880+
.iter()
881+
.map(|widget| {
882+
let axis_response = ui.allocate_rect(widget.rect, Sense::drag());
883+
if allow_axis_zoom_drag.x {
884+
axis_response.on_hover_cursor(CursorIcon::ResizeHorizontal)
885+
} else {
886+
axis_response
887+
}
888+
})
889+
.collect::<Vec<_>>();
890+
891+
let y_axis_responses = y_axis_widgets
892+
.iter()
893+
.map(|widget| {
894+
let axis_response = ui.allocate_rect(widget.rect, Sense::drag());
895+
896+
if allow_axis_zoom_drag.y {
897+
axis_response.on_hover_cursor(CursorIcon::ResizeVertical)
898+
} else {
899+
axis_response
900+
}
901+
})
902+
.collect::<Vec<_>>();
903+
866904
// Load or initialize the memory.
867905
ui.ctx().check_for_id_clash(plot_id, plot_rect, "Plot");
868906

@@ -1081,6 +1119,50 @@ impl<'a> Plot<'a> {
10811119
.translate_bounds((delta.x as f64, delta.y as f64));
10821120
mem.auto_bounds = mem.auto_bounds.and(!allow_drag);
10831121
}
1122+
// Axis zoom dragging
1123+
if allow_axis_zoom_drag.x
1124+
&& x_axis_responses
1125+
.iter()
1126+
.any(|r| r.dragged_by(PointerButton::Primary))
1127+
{
1128+
let axis_response = x_axis_responses
1129+
.iter()
1130+
.find(|r| r.dragged_by(PointerButton::Primary))
1131+
.expect("One x-axis response should be dragged");
1132+
1133+
if let Some(_hover_pos) = axis_response.hover_pos() {
1134+
let delta = axis_response.drag_delta();
1135+
let mut zoom = delta.clamp(Vec2::splat(-10.0), Vec2::splat(10.0)) / 10.0;
1136+
zoom.x += 1.0;
1137+
zoom.y = 1.0;
1138+
if zoom.x != 1.0 {
1139+
mem.transform.zoom(zoom, plot_rect.center());
1140+
mem.auto_bounds = false.into();
1141+
}
1142+
}
1143+
}
1144+
1145+
if allow_axis_zoom_drag.y
1146+
&& y_axis_responses
1147+
.iter()
1148+
.any(|r| r.dragged_by(PointerButton::Primary))
1149+
{
1150+
let axis_response = y_axis_responses
1151+
.iter()
1152+
.find(|r| r.dragged_by(PointerButton::Primary))
1153+
.expect("One y-axis response should be dragged");
1154+
1155+
if let Some(_hover_pos) = axis_response.hover_pos() {
1156+
let delta = axis_response.drag_delta();
1157+
let mut zoom = delta.clamp(Vec2::splat(-10.0), Vec2::splat(10.0)) / 10.0;
1158+
zoom.x = 1.0;
1159+
zoom.y += 1.0;
1160+
if zoom.y != 1.0 {
1161+
mem.transform.zoom(zoom, plot_rect.center());
1162+
mem.auto_bounds = false.into();
1163+
}
1164+
}
1165+
}
10841166

10851167
// Zooming
10861168
let mut boxed_zoom_rect = None;

0 commit comments

Comments
 (0)