Skip to content

Commit

Permalink
WIP: Make + and - zoom in and out, respectively
Browse files Browse the repository at this point in the history
This adds a zoom function to the PCanvas and implements for the two
current backends. For vispy, the zoom happens under the cursor, like how
the mouse wheel behaves. But for pygfx, I did not yet figure out how to
do that. Do we need to translate the focused point to the origin, then
change zoom, then translate it back?
  • Loading branch information
ctrueden committed Oct 9, 2024
1 parent 10abe13 commit 5d2e83f
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/ndv/viewer/_backends/_protocols.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ def set_range(
z: tuple[float, float] | None = None,
margin: float = ...,
) -> None: ...
def zoom(
self,
factor: float | tuple,
center: tuple | None = None,
) -> None: ...
def refresh(self) -> None: ...
def qwidget(self) -> QWidget: ...
def add_image(
Expand Down
17 changes: 17 additions & 0 deletions src/ndv/viewer/_backends/_pygfx.py
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,23 @@ def set_range(
cam.zoom = 1 - margin
self.refresh()

def zoom(self, factor: float | tuple, center: tuple | None = None):
"""
Zoom in (or out) at the given center.
Parameters
----------
factor : float or tuple
Fraction by which the scene should be zoomed (e.g. a factor of 2
causes the scene to appear twice as large).
center : tuple of 2-4 elements
The center of the view. If not given or None, use the
current center.
"""
cam = self._camera
cam.zoom *= factor
self.refresh()

Check warning on line 579 in src/ndv/viewer/_backends/_pygfx.py

View check run for this annotation

Codecov / codecov/patch

src/ndv/viewer/_backends/_pygfx.py#L577-L579

Added lines #L577 - L579 were not covered by tests

def refresh(self) -> None:
self._canvas.update()
self._canvas.request_draw(self._animate)
Expand Down
15 changes: 15 additions & 0 deletions src/ndv/viewer/_backends/_vispy.py
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,21 @@ def set_range(
max_size = max(x[1], y[1], z[1])
self._camera.scale_factor = max_size + 6

def zoom(self, factor: float | tuple, center: tuple | None = None):
"""
Zoom in (or out) at the given center.
Parameters
----------
factor : float or tuple
Fraction by which the scene should be zoomed (e.g. a factor of 2
causes the scene to appear twice as large).
center : tuple of 2-4 elements
The center of the view. If not given or None, use the
current center.
"""
return self._camera.zoom(factor=factor, center=center)

Check warning on line 596 in src/ndv/viewer/_backends/_vispy.py

View check run for this annotation

Codecov / codecov/patch

src/ndv/viewer/_backends/_vispy.py#L596

Added line #L596 was not covered by tests

def canvas_to_world(
self, pos_xy: tuple[float, float]
) -> tuple[float, float, float]:
Expand Down
8 changes: 8 additions & 0 deletions src/ndv/viewer/_viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,9 @@ def __init__(
# ROI
self._roi: PRoiHandle | None = None

# closest data point under the mouse
self._data_coords: tuple[int, int] = (0, 0)

# WIDGETS ----------------------------------------------------

# the button that controls the display mode of the channels
Expand Down Expand Up @@ -731,6 +734,7 @@ def _update_hover_info(self, event: QMouseEvent) -> bool:

x = int(x)
y = int(y)
self._data_coords = (x, y)
text = f"[{y}, {x}]"
# TODO: Can we use self._canvas.elements_at?
for n, handles in enumerate(self._img_handles.values()):
Expand Down Expand Up @@ -765,6 +769,10 @@ def keyPressEvent(self, a0: QKeyEvent | None) -> None:
if a0.key() == Qt.Key.Key_Delete and self._selection is not None:
self._selection.remove()
self._selection = None
elif a0.key() in [Qt.Key.Key_Plus, Qt.Key.Key_Equal]:
self._canvas.zoom(factor=0.667, center=self._data_coords)
elif a0.key() in [Qt.Key.Key_Minus, Qt.Key.Key_Underscore]:
self._canvas.zoom(factor=1.5, center=self._data_coords)

Check warning on line 775 in src/ndv/viewer/_viewer.py

View check run for this annotation

Codecov / codecov/patch

src/ndv/viewer/_viewer.py#L772-L775

Added lines #L772 - L775 were not covered by tests

def _update_roi_button(self, event: QMouseEvent) -> bool:
if self._add_roi_btn.isChecked():
Expand Down

0 comments on commit 5d2e83f

Please sign in to comment.