user-interfaceplotmatplotlibzooming

Matplotlib plot zooming with scroll wheel


Is it possible to bind the scroll wheel to zoom in/out when the cursor is hovering over a matplotlib plot?


Solution

  • This should work. It re-centers the graph on the location of the pointer when you scroll.

    import matplotlib.pyplot as plt
    
    
    def zoom_factory(ax,base_scale = 2.):
        def zoom_fun(event):
            # get the current x and y limits
            cur_xlim = ax.get_xlim()
            cur_ylim = ax.get_ylim()
            cur_xrange = (cur_xlim[1] - cur_xlim[0])*.5
            cur_yrange = (cur_ylim[1] - cur_ylim[0])*.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
            else:
                # deal with something that should never happen
                scale_factor = 1
                print event.button
            # 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])
            plt.draw() # force re-draw
            
        fig = ax.get_figure() # get the figure of interest
        # attach the call back
        fig.canvas.mpl_connect('scroll_event',zoom_fun)
    
        #return the function
        return zoom_fun
            
    

    Assuming you have an axis object ax

    ax.plot(range(10))
    scale = 1.5
    f = zoom_factory(ax,base_scale = scale)
    

    The optional argument base_scale allows you to set the scale factor to be what ever you want.

    Make sure you keep a copy of f around. The call back uses a weak-ref so if you do not keep a copy of f it might be garbage collected.

    After writing this answer I decided this actually quite useful and put it in a gist