from Mouse-friendly FIGURE by Rody Oldenhuis
Same as FIGURE, but zooming/panning is done more conveniently with scroll wheel/clicks.

mouse_figure(MainFig)
function MainFig = mouse_figure(MainFig)
%MOUSE_FIGURE           mouse-friendly figure
%
% MOUSE_FIGURE() creates a figure (or modifies an existing one) that allows
% zooming with the scroll wheel and panning with mouse clicks, *without*
% first selecting the ZOOM or PAN tools from the toolbar. Moreover, zooming
% occurs to and from the point the mouse currently hovers over, instead of
% to and from the less intuitive "CameraPosition". 
%
%         Scroll: zoom in/out
%     Left click: pan
%   Double click: reset view to default view
%    Right click: set new default view
%
% LIMITATIONS: This function (re-)efines several functions in the figure 
% (WindowScrollWheelFcn, WindowButtonDownFcn, WindowButtonUpFcn and 
% WindowButtonMotionFcn), so if you have any of these functions already
% defined they will get overwritten. Also, MOUSE_FIGURE() only works 
% properly for 2-D plots. As such, it should only be used for simple, 
% first-order plots intended for "quick-n-dirty" data exploration.
%
% EXAMPLE:
%
%   mouse_figure;
%   x = linspace(-1, 1, 10000);
%   y = sin(1./x);
%   plot(x, y) 
%   
% See also figure, axes, zoom, pan.


%      Author : Rody P.S. Oldenhuis
% Affiliation : Delft University of Technology
%               Faculty of Aerospace Engineering
%               Dep. of Astrodynamics & Satellite Systems 
%     Contact : oldenhuis@dds.nl
%   Licensing/
%    (C) info : Frankly I don't care what you do with it, 
%               as long as I get some credit when you copy 
%               practically the exact code ^_^
    
    % initialize
    status = '';  previous_point = [];
    
    % initialize axes
    if (nargin == 0) || ~ishandle(MainFig)
        MainFig = figure;  axs = gca;
    else
        axs = get(MainFig, 'currentaxes');
    end
    
    % only works properly for 2D plots
    if ~is2D(axs) % is2D might disappear in a future release...
        error('mouse_figure:plot3D_not_supported', ...
              'MOUSE_FIGURE() only works for 2-D plots.');
    end
        
    % get original limits
    original_xlim = get(axs, 'xlim');
    original_ylim = get(axs, 'ylim');
    
    % define zooming with scrollwheel, and panning with mouseclicks
    set(MainFig, ...
        'WindowScrollWheelFcn' , @scroll_zoom,...
        'WindowButtonDownFcn'  , @pan_click,...
        'WindowButtonUpFcn'    , @pan_release,...
        'WindowButtonMotionFcn', @pan_motion);    
    
    % zoom in to the current point with the mouse wheel
    function scroll_zoom(varargin)
        % double check if these axes are indeed the current axes
        if get(MainFig, 'currentaxes') ~= axs, return, end
        % get the amount of scolls
        scrolls = varargin{2}.VerticalScrollCount;
        % get the axes' x- and y-limits
        xlim = get(axs, 'xlim');  ylim = get(axs, 'ylim');
        % get the current camera position, and save the [z]-value
        cam_pos_Z = get(axs, 'cameraposition');  cam_pos_Z = cam_pos_Z(3);
        % get the current point
        old_position = get(axs, 'CurrentPoint'); old_position(1,3) = cam_pos_Z;
        % calculate zoom factor
        zoomfactor = 1 - scrolls/50;
        % adjust camera position
        set(axs, 'cameratarget', [old_position(1, 1:2), 0],...
            'cameraposition', old_position(1, 1:3));
        % adjust the camera view angle (equal to zooming in)
        camzoom(zoomfactor);
        % zooming with the camera has the side-effect of
        % NOT adjusting the axes limits. We have to correct for this:
        x_lim1 = (old_position(1,1) - min(xlim))/zoomfactor;
        x_lim2 = (max(xlim) - old_position(1,1))/zoomfactor;
        xlim   = [old_position(1,1) - x_lim1, old_position(1,1) + x_lim2];
        y_lim1 = (old_position(1,2) - min(ylim))/zoomfactor;
        y_lim2 = (max(ylim) - old_position(1,2))/zoomfactor;
        ylim   = [old_position(1,2) - y_lim1, old_position(1,2) + y_lim2];
        set(axs, 'xlim', xlim), set(axs, 'ylim', ylim)
        % set new camera position
        new_position = get(axs, 'CurrentPoint');
        old_camera_target =  get(axs, 'CameraTarget');
        old_camera_target(3) = cam_pos_Z;
        new_camera_position = old_camera_target - ...
            (new_position(1,1:3) - old_camera_target(1,1:3));
        % adjust camera target and position
        set(axs, 'cameraposition', new_camera_position(1, 1:3),...
            'cameratarget', [new_camera_position(1, 1:2), 0]);
        % we also have to re-set the axes to stretch-to-fill mode
        set(axs, 'cameraviewanglemode', 'auto',...
            'camerapositionmode', 'auto',...
            'cameratargetmode', 'auto');
    end % scroll_zoom
    
    % pan upon mouse click
    function pan_click(varargin)
        % double check if these axes are indeed the current axes
        if get(MainFig, 'currentaxes') ~= axs, return, end
        % perform appropriate action
        switch lower(get(MainFig, 'selectiontype'))            
            % start panning on left click
            case 'normal' 
                status = 'down';
                previous_point = get(axs, 'CurrentPoint');              
            % reset view on double click
            case 'open' % double click (left or right)
                set(axs, 'Xlim', original_xlim,...
                         'Ylim', original_ylim);  
            % right click - set new reset state
            case 'alt'
                original_xlim = get(axs, 'xlim');
                original_ylim = get(axs, 'ylim');
        end
    end
    
    % release mouse button
    function pan_release(varargin)
        % double check if these axes are indeed the current axes
        if get(MainFig, 'currentaxes') ~= axs, return, end
        % just reset status
        status = '';
    end
    
    % move the mouse (with button clicked)
    function pan_motion(varargin)
        % double check if these axes are indeed the current axes
        if get(MainFig, 'currentaxes') ~= axs, return, end
        % return if there isn't a previous point
        if isempty(previous_point), return, end  
        % return if mouse hasn't been clicked
        if isempty(status), return, end  
        % get current location (in pixels)
        current_point = get(axs, 'CurrentPoint');
        % get current XY-limits
        xlim = get(axs, 'xlim');  ylim = get(axs, 'ylim');     
        % find change in position
        delta_points = current_point - previous_point;  
        % adjust limits
        new_xlim = xlim - delta_points(1); 
        new_ylim = ylim - delta_points(3); 
        % set new limits
        set(axs, 'Xlim', new_xlim); set(axs, 'Ylim', new_ylim);           
        % save new position
        previous_point = get(axs, 'CurrentPoint');
    end 
    
end

Contact us at files@mathworks.com