diff --git a/doc/release/next_whats_new/scroll_to_zoom.rst b/doc/release/next_whats_new/scroll_to_zoom.rst index bafa312c32a5..1be522b7a255 100644 --- a/doc/release/next_whats_new/scroll_to_zoom.rst +++ b/doc/release/next_whats_new/scroll_to_zoom.rst @@ -2,7 +2,8 @@ Zooming using mouse wheel ~~~~~~~~~~~~~~~~~~~~~~~~~ ``Ctrl+MouseWheel`` can be used to zoom in the plot windows. +Additionally, ``x+MouseWheel`` zooms only the x-axis and ``y+MouseWheel`` zooms only the y-axis. -The zoom focusses on the mouse pointer, and keeps the aspect ratio of the axes. +The zoom focusses on the mouse pointer. With ``Ctrl``, the axes aspect ratio is kept; with ``x`` or ``y``, only the respective axis is scaled. Zooming is currently only supported on rectilinear Axes. diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index 7560db80d2c1..07a48a768de0 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -2592,7 +2592,7 @@ def scroll_handler(event, canvas=None, toolbar=None): # is required for interactive navigation. return - if event.key == "control": # zoom towards the mouse position + if event.key in {"control", "x", "y"}: # zoom towards the mouse position toolbar.push_current() xmin, xmax = ax.get_xlim() @@ -2604,10 +2604,21 @@ def scroll_handler(event, canvas=None, toolbar=None): x, y = ax.transScale.transform((event.xdata, event.ydata)) scale_factor = 0.85 ** event.step - new_xmin = x - (x - xmin) * scale_factor - new_xmax = x + (xmax - x) * scale_factor - new_ymin = y - (y - ymin) * scale_factor - new_ymax = y + (ymax - y) * scale_factor + # Determine which axes to scale based on key + zoom_x = event.key in {"control", "x"} + zoom_y = event.key in {"control", "y"} + + if zoom_x: + new_xmin = x - (x - xmin) * scale_factor + new_xmax = x + (xmax - x) * scale_factor + else: + new_xmin, new_xmax = xmin, xmax + + if zoom_y: + new_ymin = y - (y - ymin) * scale_factor + new_ymax = y + (ymax - y) * scale_factor + else: + new_ymin, new_ymax = ymin, ymax inv_scale = ax.transScale.inverted() (new_xmin, new_ymin), (new_xmax, new_ymax) = inv_scale.transform(