Code covered by the BSD License  

Highlights from
TextZoomable for text that scales as you zoom

image thumbnail

TextZoomable for text that scales as you zoom

by

 

Adds text to a figure that grows/shrinks with figure content as the figure is zoomed/scaled

TextZoomable(x,y,varargin)
function txtHandle = TextZoomable(x,y,varargin)
% txtHandle = FixedSizeText(x,y,varargin)
% 
% Adds text to a figure in the normal manner, except that this text
% grows/shrinks with figure scaling and zooming, unlike normal text that
% stays at a fixed font size during figure operations. Note it scales with
% figure height - for best scaling use 'axis equal' before setting up the
% text.
%
% All varargin{:} arguments will be passed directly on to the text
% function (text properties, etc.)
%
% (doesn't behave well with FontUnits = 'normalized')
%
% example:
% 
% figure(1); clf;
% rectangle('Position', [0 0 1 1]);
% rectangle('Position', [.25 .25 .5 .5]);
% 
% th = TextZoomable(.5, .5, 'red', 'color', [1 0 0], 'Clipping', 'on');
% th2 = TextZoomable(.5, .1, 'blue', 'color', [0 0 1]);
%
%
% Ken Purchase, 4-25-2013
%
%

    % create the text
    txtHandle = text(x,y,varargin{:});

    % detect its size relative to the figure, and set up listeners to resize
    % it as the figure resizes, or axis limits are changed.
    hAx = gca;
    hFig = get(hAx,'Parent');
    
    fs = get(txtHandle, 'FontSize');
    ratios = fs * diff(get(hAx,'YLim')) / max(get(hFig,'Position') .* [0 0 0 1]);
    
    
    % append the handles and ratios to the user data - repeated calls will
    % add each block of text to the list
    ud = get(hAx, 'UserData');
    if isfield(ud, 'ratios')
        ud.ratios = [ud.ratios(:); ratios];
    else
        ud.ratios = ratios;
    end
    if isfield(ud, 'handles')
        ud.handles = [ud.handles(:); txtHandle];
    else
        ud.handles = txtHandle;
    end
    
    set(hAx,'UserData', ud);
    localSetupPositionListener(hFig,hAx);
    localSetupLimitListener(hAx);

end


%% Helper Functions

function fs = getBestFontSize(imAxes)
    % Try to keep font size reasonable for text
    hFig = get(imAxes,'Parent');
    hFigFactor = max(get(hFig,'Position') .* [0 0 0 1]);  
    axHeight = diff(get(imAxes,'YLim'));
    ud = get(imAxes,'UserData');  % stored in teh first user data.
    fs = round(ud.ratios * hFigFactor / axHeight);    
    fs = max(fs, 3);
end

function localSetupPositionListener(hFig,imAxes)
    % helper function to sets up listeners for resizing, so we can detect if
    % we would need to change the fontsize
    PostPositionListener = handle.listener(hFig,'ResizeEvent',...
        {@localPostPositionListener,imAxes});
    setappdata(hFig,'KenFigResizeListeners',PostPositionListener);
end

function localPostPositionListener(~,~,imAxes) 
    % when called, rescale all fonts in image
    ud = get(imAxes,'UserData');
    fs = getBestFontSize(imAxes);
    for ii = 1:length(ud.handles)
        set(ud.handles(ii),'fontsize',fs(ii),'visible','on');
    end   
end

function localSetupLimitListener(imAxes)
    % helper function to sets up listeners for zooming, so we can detect if
    % we would need to change the fontsize
    hgp     = findpackage('hg');
    axesC   = findclass(hgp,'axes');
    LimListener = handle.listener(imAxes,[axesC.findprop('XLim') axesC.findprop('YLim')],...
        'PropertyPostSet',@localLimitListener);
    hFig = get(imAxes,'Parent');
    setappdata(hFig,'KenAxeResizeListeners',LimListener);
end

function localLimitListener(~,event)
    % when called, rescale all fonts in image
    imAxes = event.AffectedObject;
    ud = get(imAxes,'UserData');
    fs = getBestFontSize(imAxes);
    for ii = 1:length(ud.handles)
        set(ud.handles(ii),'fontsize',fs(ii),'visible','on');
    end
end

Contact us