Skip to content

Commit 21fc347

Browse files
committed
FIX: Allow colorbar zoom when the short-axis values are close
Colorbars are one-dimensional, so we don't want to cancel the zoom based on the short-axis. This also updates the test to account for this case.
1 parent e1f9cc9 commit 21fc347

File tree

2 files changed

+33
-18
lines changed

2 files changed

+33
-18
lines changed

lib/matplotlib/backend_bases.py

+27-15
Original file line numberDiff line numberDiff line change
@@ -3137,7 +3137,7 @@ def zoom(self, *args):
31373137
a.set_navigate_mode(self.mode._navigate_mode)
31383138
self.set_message(self.mode)
31393139

3140-
_ZoomInfo = namedtuple("_ZoomInfo", "direction start_xy axes cid")
3140+
_ZoomInfo = namedtuple("_ZoomInfo", "direction start_xy axes cid cbar")
31413141

31423142
def press_zoom(self, event):
31433143
"""Callback for mouse button press in zoom to rect mode."""
@@ -3152,29 +3152,34 @@ def press_zoom(self, event):
31523152
self.push_current() # set the home button to this view
31533153
id_zoom = self.canvas.mpl_connect(
31543154
"motion_notify_event", self.drag_zoom)
3155+
# A colorbar is one-dimensional, so we extend the zoom rectangle out
3156+
# to the edge of the axes bbox in the other dimension. To do that we
3157+
# store the orientation of the colorbar for later.
3158+
if hasattr(axes[0], "_colorbar"):
3159+
cbar = axes[0]._colorbar.orientation
3160+
else:
3161+
cbar = None
31553162
self._zoom_info = self._ZoomInfo(
31563163
direction="in" if event.button == 1 else "out",
3157-
start_xy=(event.x, event.y), axes=axes, cid=id_zoom)
3164+
start_xy=(event.x, event.y), axes=axes, cid=id_zoom, cbar=cbar)
31583165

31593166
def drag_zoom(self, event):
31603167
"""Callback for dragging in zoom mode."""
31613168
start_xy = self._zoom_info.start_xy
31623169
ax = self._zoom_info.axes[0]
31633170
(x1, y1), (x2, y2) = np.clip(
31643171
[start_xy, [event.x, event.y]], ax.bbox.min, ax.bbox.max)
3165-
if event.key == "x":
3172+
key = event.key
3173+
# Force the key on colorbars to extend the short-axis bbox
3174+
if self._zoom_info.cbar == "horizontal":
3175+
key = "x"
3176+
elif self._zoom_info.cbar == "vertical":
3177+
key = "y"
3178+
if key == "x":
31663179
y1, y2 = ax.bbox.intervaly
3167-
elif event.key == "y":
3180+
elif key == "y":
31683181
x1, x2 = ax.bbox.intervalx
31693182

3170-
# A colorbar is one-dimensional, so we extend the zoom rectangle out
3171-
# to the edge of the axes bbox in the other dimension
3172-
if hasattr(ax, "_colorbar"):
3173-
if ax._colorbar.orientation == 'horizontal':
3174-
y1, y2 = ax.bbox.intervaly
3175-
else:
3176-
x1, x2 = ax.bbox.intervalx
3177-
31783183
self.draw_rubberband(event, x1, y1, x2, y2)
31793184

31803185
def release_zoom(self, event):
@@ -3188,10 +3193,17 @@ def release_zoom(self, event):
31883193
self.remove_rubberband()
31893194

31903195
start_x, start_y = self._zoom_info.start_xy
3196+
key = event.key
3197+
# Force the key on colorbars to ignore the zoom-cancel on the
3198+
# short-axis side
3199+
if self._zoom_info.cbar == "horizontal":
3200+
key = "x"
3201+
elif self._zoom_info.cbar == "vertical":
3202+
key = "y"
31913203
# Ignore single clicks: 5 pixels is a threshold that allows the user to
31923204
# "cancel" a zoom action by zooming by less than 5 pixels.
3193-
if ((abs(event.x - start_x) < 5 and event.key != "y")
3194-
or (abs(event.y - start_y) < 5 and event.key != "x")):
3205+
if ((abs(event.x - start_x) < 5 and key != "y") or
3206+
(abs(event.y - start_y) < 5 and key != "x")):
31953207
self.canvas.draw_idle()
31963208
self._zoom_info = None
31973209
return
@@ -3205,7 +3217,7 @@ def release_zoom(self, event):
32053217
for prev in self._zoom_info.axes[:i])
32063218
ax._set_view_from_bbox(
32073219
(start_x, start_y, event.x, event.y),
3208-
self._zoom_info.direction, event.key, twinx, twiny)
3220+
self._zoom_info.direction, key, twinx, twiny)
32093221

32103222
self.canvas.draw_idle()
32113223
self._zoom_info = None

lib/matplotlib/tests/test_backend_bases.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -202,10 +202,13 @@ def test_interactive_colorbar(plot_func, orientation, tool, button, expected):
202202
assert cb.ax.get_navigate()
203203

204204
# Mouse from 4 to 6 (data coordinates, "d").
205-
# The y coordinate doesn't matter, just needs to be between 0 and 1
206205
vmin, vmax = 4, 6
207-
d0 = (vmin, 0.1)
208-
d1 = (vmax, 0.9)
206+
# The y coordinate doesn't matter, it just needs to be between 0 and 1
207+
# However, we will set d0/d1 to the same y coordinate to test that small
208+
# pixel changes in that coordinate doesn't cancel the zoom like a normal
209+
# axes would.
210+
d0 = (vmin, 0.5)
211+
d1 = (vmax, 0.5)
209212
# Swap them if the orientation is vertical
210213
if orientation == "vertical":
211214
d0 = d0[::-1]

0 commit comments

Comments
 (0)