|import matplotlib.pyplot as plt|
|def zoom_factory(ax,base_scale = 2.):|
|# get the current x and y limits|
|cur_xlim = ax.get_xlim()|
|cur_ylim = ax.get_ylim()|
|# set the range|
|cur_xrange = (cur_xlim - cur_xlim)*.5|
|cur_yrange = (cur_ylim - cur_ylim)*.5|
|xdata = event.xdata # get event x location|
|ydata = event.ydata # get event y location|
|if event.button == 'up':|
|# deal with zoom in|
|scale_factor = 1/base_scale|
|elif event.button == 'down':|
|# deal with zoom out|
|scale_factor = base_scale|
|# deal with something that should never happen|
|scale_factor = 1|
|# set new limits|
|ax.set_xlim([xdata - cur_xrange*scale_factor,|
|xdata + cur_xrange*scale_factor])|
|ax.set_ylim([ydata - cur_yrange*scale_factor,|
|ydata + cur_yrange*scale_factor])|
|ax.figure.canvas.draw_idle() # force re-draw the next time the GUI refreshes|
|fig = ax.get_figure() # get the figure of interest|
|# attach the call back|
|#return the function|
IMHO, I think we don't have to calculate the
# Get distance from the cursor to the edge of the figure frame x_left = xdata - cur_xlim x_right = cur_xlim - xdata y_top = ydata - cur_ylim y_bottom = cur_ylim - ydata
then set the new
ax.set_xlim([xdata - x_left*scale_factor, xdata + x_right*scale_factor]) ax.set_ylim([ydata - y_top*scale_factor, ydata + y_bottom*scale_factor])
By this way, when zooming in and zooming out, the pixel which the cursor is pointing to won't be changed.
I'm new to matplotlib. Trying to support zoom on a scatterplot programatically.
Thank you guys! I've found beneficial to implement 'event.step'. Posting the code.
My own implementation into Qt from mine project (stripped a bit) - shift selects the axis and also mods functionality:
There is another way of doing it as far as I know. By chance I came across the Axis.zoom method. I don't know if this is faster or a good way in general, but it works and is certainly less code:
If you plot an image though, for some reason, you have to invert the y-axis again.
If you're using this in an environment with a toolbar and you want the home button to return to the original view after zooming:
you could also add this to the zoom factory, but that may be risky as I'm not sure that
that gist also does some nice checking inside of
toolbar = ax.get_figure().canvas.toolbar # only set the home state if toolbar._views.empty(): toolbar.push_current()
This may help.
I've been using it quite happily but my code is a bit too specific but derived from simp_zoom.py
@mapfiable Interesting, I also did not know that existing until you pointed it out! The reason for the re-inversion is that you can invert the axis by setting the "min" to be greater than the "max" and inside of
The workaround I used for this was to to use jupyterlab sidecar widget to display the plot as that won't have a scroll bar so it doesn't matter that the scroll input wasn't captured. Long term - I opened an issue and PR about this matplotlib/ipympl#222 that I think would fix this.
Hey, I tried to implement this in a wxPython Frame, but I keep getting a TypeError: zoom_fun() missing 1 required positional argument: 'event'. I know how to solve missing events in wxPython, but not in matplotlib. It should work because otherwise I wouldn't be getting the error on scrolling...