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

 

Text that zooms as you zoom your plot, rather than staying at a fixed font size.

Editor's Notes:

This file was selected as MATLAB Central Pick of the Week

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