Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions doc/release/next_whats_new/scroll_to_zoom.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Zooming using mouse wheel
~~~~~~~~~~~~~~~~~~~~~~~~~

``Ctrl+MouseWheel`` can be used to zoom in the plot windows.

The zoom focusses on the mouse pointer, and keeps the aspect ratio of the axes.

Zooming is currently only supported on rectilinear Axes.
48 changes: 48 additions & 0 deletions lib/matplotlib/backend_bases.py
Original file line number Diff line number Diff line change
Expand Up @@ -2574,6 +2574,51 @@ def button_press_handler(event, canvas=None, toolbar=None):
toolbar.forward()


def scroll_handler(event, canvas=None, toolbar=None):
ax = event.inaxes
if ax is None:
return
if ax.name != "rectilinear":
# zooming is currently only supported on rectilinear axes
return

if toolbar is None:
toolbar = (canvas or event.canvas).toolbar

if toolbar is None:
# technically we do not need a toolbar, but until wheel zoom was
# introduced, any interactive modification was only possible through
# the toolbar tools. For now, we keep the restriction that a toolbar
# is required for interactive navigation.
return

if event.key == "control": # zoom towards the mouse position
toolbar.push_current()

xmin, xmax = ax.get_xlim()
ymin, ymax = ax.get_ylim()
(xmin, ymin), (xmax, ymax) = ax.transScale.transform(
[(xmin, ymin), (xmax, ymax)])

# mouse position in scaled (e.g., log) data coordinates
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

inv_scale = ax.transScale.inverted()
(new_xmin, new_ymin), (new_xmax, new_ymax) = inv_scale.transform(
[(new_xmin, new_ymin), (new_xmax, new_ymax)])

ax.set_xlim(new_xmin, new_xmax)
ax.set_ylim(new_ymin, new_ymax)

ax.figure.canvas.draw_idle()


class NonGuiException(Exception):
"""Raised when trying show a figure in a non-GUI backend."""
pass
Expand Down Expand Up @@ -2653,11 +2698,14 @@ def __init__(self, canvas, num):

self.key_press_handler_id = None
self.button_press_handler_id = None
self.scroll_handler_id = None
if rcParams['toolbar'] != 'toolmanager':
self.key_press_handler_id = self.canvas.mpl_connect(
'key_press_event', key_press_handler)
self.button_press_handler_id = self.canvas.mpl_connect(
'button_press_event', button_press_handler)
self.scroll_handler_id = self.canvas.mpl_connect(
'scroll_event', scroll_handler)

self.toolmanager = (ToolManager(canvas.figure)
if mpl.rcParams['toolbar'] == 'toolmanager'
Expand Down
6 changes: 6 additions & 0 deletions lib/matplotlib/backend_bases.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,11 @@ def button_press_handler(
canvas: FigureCanvasBase | None = ...,
toolbar: NavigationToolbar2 | None = ...,
) -> None: ...
def scroll_handler(
event: MouseEvent,
canvas: FigureCanvasBase | None = ...,
toolbar: NavigationToolbar2 | None = ...,
) -> None: ...

class NonGuiException(Exception): ...

Expand All @@ -415,6 +420,7 @@ class FigureManagerBase:
num: int | str
key_press_handler_id: int | None
button_press_handler_id: int | None
scroll_handler_id: int | None
toolmanager: ToolManager | None
toolbar: NavigationToolbar2 | ToolContainerBase | None
def __init__(self, canvas: FigureCanvasBase, num: int | str) -> None: ...
Expand Down
Loading