@jfruan
        
        2017-04-14T00:49:27.000000Z
        字数 14743
        阅读 2582
    Matlab
Rotate x-tick labels to any angle, preserving font settings and coping with resize, zoom, pan etc. 
The MATLAB plot gallery provides examples of many ways to display data graphically in MATLAB. You can view and download source code for each plot, and use it in your own MATLAB project. 
Get started with Plotly's MATLAB graphing library to make interactive, publication-quality graphs online.
clear% file sizex=[136,148,158,168,178,188,198,208,228,248,276,296,316,336,356];% read localy11 = [0.4768,0.8226,0.8697,0.9738,0.9484,0.9763,0.9703,0.9602,0.9786,0.952,0.852,0.9142,0.9341,0.9365,0.9162]';% write localy12 = [0.9706,0.9673,0.984,0.9174,0.9816,0.9396,0.9429,0.9385,0.9221,0.8361,0.9497,0.9266,0.936,0.9463,0.9456]';% read awsy21 = [0.5808,0.7663,0.7880,0.8978,0.8560,0.9079,0.8860,0.8784,0.9048,0.8770,0.8032,0.8396,0.8528,0.8745,0.8557]';% write awsy22 = [0.8161,0.7515,0.8364,0.8029,0.8265,0.8200,0.8194,0.8583,0.8290,0.7487,0.8392,0.7737,0.8248,0.8034,0.7700]';% localdata1 = [y11, y12];% awsdata2 = [y21, y22];b = bar(data1,1.0);b(1).FaceColor = [1 128 104]/255;% b(2).FaceColor = [129 192 100]/255b(2).FaceColor = [255 255 102]/255;set(gcf,'unit','centimeters','position',[10 10 20 15])% set(gca,'YLim',[0 1.2]); %Y轴的数据显示范围set(gca,'XTickLabel',{'136','148','158','168','178','188','198','208','228','248','276','296','316','336','356'})h = gca;rotateXLabels(h, 45); %旋转角度xlabel('File size (MB)'),ylabel('Similarity')hl = legend('HDFS read operation ','HDFS write operation');set(hl,'Location','northoutside','Orientation','horizontal')set(gca,'FontSize',15);set(gca,'FontName','Times new roman');
For releases prior to R2016b, specify the rotation using the XTickLabelRotation and YTickLabelRotation properties of the Axes object. For example, assign the Axes object to a variable, such as ax = gca. Then set the XTickLabelRotation property using dot notation, such as ax.XTickLabelRotation = 45.
% For Matlab R2016bx = linspace(0,10000,21);y = x.^2;stem(x,y)ax = gcaax.XTickLabelRotation = 45
% Start with Matlab R2014b, prior to R2016bx = 1000*rand(40,1);y = rand(40,1);scatter(x,y)xtickangle(45)ytickangle(90)


function hh = rotateXLabels( ax, angle, varargin )%rotateXLabels: rotate any xticklabels%% hh = rotateXLabels(ax,angle) rotates all XLabels on axes AX by an angle% ANGLE (in degrees). Handles to the resulting text objects are returned% in HH.%% hh = rotateXLabels(ax,angle,param,value,...) also allows one or more% optional parameters to be specified. Possible parameters are:% 'MaxStringLength' The maximum length of label to show (default inf)%% Examples:% >> bar( hsv(5)+0.05 )% >> days = {'Monday','Tuesday','Wednesday','Thursday','Friday'};% >> set( gca(), 'XTickLabel', days )% >> rotateXLabels( gca(), 45 )%% See also: GCA, BAR% Copyright 2006-2013 The MathWorks Ltd.error( nargchk( 2, inf, nargin ) );if ~isnumeric( angle ) || ~isscalar( angle )error( 'RotateXLabels:BadAngle', 'Parameter ANGLE must be a scalar angle in degrees' )endangle = mod( angle, 360 );% From R2014b, rotating labels is built-in using 'XTickLabelRotation'if ~verLessThan('matlab','8.4.0')set(ax, 'XTickLabelRotation', angle)if nargout > 1hh = [];endreturn;end[maxStringLength] = parseInputs( varargin{:} );% Get the existing label texts and clear them[vals, labels] = findAndClearExistingLabels( ax, maxStringLength );% Create the new label textsh = createNewLabels( ax, vals, labels, angle );% Reposition the axes itself to leave space for the new labelsrepositionAxes( ax );% If an X-label is present, move it toorepositionXLabel( ax );% Store anglesetappdata( ax, 'RotateXLabelsAngle', angle );% Only send outputs if requestedif nargouthh = h;end%-------------------------------------------------------------------------%function [maxStringLength] = parseInputs( varargin )% Parse optional inputsmaxStringLength = inf;if nargin > 0params = varargin(1:2:end);values = varargin(2:2:end);if numel( params ) ~= numel( values )error( 'RotateXLabels:BadSyntax', 'Optional arguments must be specified as parameter-value pairs.' );endif any( ~cellfun( 'isclass', params, 'char' ) )error( 'RotateXLabels:BadSyntax', 'Optional argument names must be specified as strings.' );endfor pp=1:numel( params )switch upper( params{pp} )case 'MAXSTRINGLENGTH'maxStringLength = values{pp};otherwiseerror( 'RotateXLabels:BadParam', 'Optional parameter ''%s'' not recognised.', params{pp} );endendendend % parseInputs%-------------------------------------------------------------------------%function [vals,labels] = findAndClearExistingLabels( ax, maxStringLength )% Get the current tick positions so that we can place our new labelsvals = get( ax, 'XTick' );% Now determine the labels. We look first at for previously rotated labels% since if there are some the actual labels will be empty.ex = findall( ax, 'Tag', 'RotatedXTickLabel' );if isempty( ex )% Store the positions and labelslabels = get( ax, 'XTickLabel' );if isempty( labels )% No labels!returnelseif ~iscell(labels)labels = cellstr(labels);endend% Clear existing labels so that xlabel is in the right positionset( ax, 'XTickLabel', {}, 'XTickMode', 'Manual' );setappdata( ax, 'OriginalXTickLabels', labels );else% Labels have already been rotated, so capture themlabels = getappdata( ax, 'OriginalXTickLabels' );set(ex, 'DeleteFcn', []);delete(ex);end% Limit the length, if requestedif isfinite( maxStringLength )for ll=1:numel( labels )if length( labels{ll} ) > maxStringLengthlabels{ll} = labels{ll}(1:maxStringLength);endendendend % findAndClearExistingLabels%-------------------------------------------------------------------------%function restoreDefaultLabels( ax )% Restore the default axis behaviorremoveListeners( ax );% Try to restore the tick marks and labelsset( ax, 'XTickMode', 'auto', 'XTickLabelMode', 'auto' );rmappdata( ax, 'OriginalXTickLabels' );% Try to restore the axes positionif isappdata( ax, 'OriginalAxesPosition' )set( ax, 'Position', getappdata( ax, 'OriginalAxesPosition' ) );rmappdata( ax, 'OriginalAxesPosition' );endend%-------------------------------------------------------------------------%function textLabels = createNewLabels( ax, vals, labels, angle )% Work out the ticklabel positionszlim = get(ax,'ZLim');z = zlim(1);% We want to work in normalised coords, but this doesn't print% correctly. Instead we have to work in data units even though it% makes positioning hard.y = getYPositionToUse( ax );% Now create new text objects in similar positions.textLabels = -1*ones( numel( vals ), 1 );for ll=1:numel(vals)textLabels(ll) = text( ...'Units', 'Data', ...'Position', [vals(ll), y, z], ...'String', labels{ll}, ...'Parent', ax, ...'Clipping', 'off', ...'Rotation', angle, ...'Tag', 'RotatedXTickLabel', ...'UserData', vals(ll));end% So that we can respond to CLA and CLOSE, attach a delete% callback. We only attach it to one label to save massive numbers% of callbacks during axes shut-down.set(textLabels(end), 'DeleteFcn', @onTextLabelDeleted);% Now copy font properties into the textsupdateFont();% Update the alignment of the textupdateAlignment();end % createNewLabels%-------------------------------------------------------------------------%function repositionAxes( ax )% Reposition the axes so that there's room for the labels% Note that we only do this if the OuterPosition is the thing being% controlledif ~strcmpi( get( ax, 'ActivePositionProperty' ), 'OuterPosition' )return;end% Work out the maximum height required for the labelslabelHeight = getLabelHeight(ax);% Remove listeners while we mess around with things, otherwise we'll% trigger redraws recursivelyremoveListeners( ax );% Change to normalized units for the position calculationoldUnits = get( ax, 'Units' );set( ax, 'Units', 'Normalized' );% Not sure why, but the extent seems to be proportional to the height of the axes.% Correct that now.set( ax, 'ActivePositionProperty', 'Position' );pos = get( ax, 'Position' );axesHeight = pos(4);% Make sure we don't adjust away the axes entirely!heightAdjust = min( (axesHeight*0.9), labelHeight*axesHeight );% Move the axesif isappdata( ax, 'OriginalAxesPosition' )pos = getappdata( ax, 'OriginalAxesPosition' );elsepos = get(ax,'Position');setappdata( ax, 'OriginalAxesPosition', pos );endif strcmpi( get( ax, 'XAxisLocation' ), 'Bottom' )% Move it up and reduce the heightset( ax, 'Position', pos+[0 heightAdjust 0 -heightAdjust] )else% Just reduce the heightset( ax, 'Position', pos+[0 0 0 -heightAdjust] )endset( ax, 'Units', oldUnits );set( ax, 'ActivePositionProperty', 'OuterPosition' );% Make sure we find out if axes properties are changedaddListeners( ax );end % repositionAxes%-------------------------------------------------------------------------%function repositionXLabel( ax )% Try to work out where to put the xlabelremoveListeners( ax );labelHeight = getLabelHeight(ax);% Use the new max extent to move the xlabel. We may also need to% move the titlexlab = get(ax,'XLabel');titleh = get( ax, 'Title' );set( [xlab,titleh], 'Units', 'Normalized' );if strcmpi( get( ax, 'XAxisLocation' ), 'Top' )titleExtent = get( xlab, 'Extent' );set( xlab, 'Position', [0.5 1+labelHeight-titleExtent(4) 0] );set( titleh, 'Position', [0.5 1+labelHeight 0] );elseset( xlab, 'Position', [0.5 -labelHeight 0] );set( titleh, 'Position', [0.5 1 0] );endaddListeners( ax );end % repositionXLabel%-------------------------------------------------------------------------%function height = getLabelHeight(ax)height = 0;textLabels = findall( ax, 'Tag', 'RotatedXTickLabel' );if isempty(textLabels)return;endoldUnits = get( textLabels(1), 'Units' );set( textLabels, 'Units', 'Normalized' );for ll=1:numel(vals)ext = get( textLabels(ll), 'Extent' );if ext(4) > heightheight = ext(4);endendset( textLabels, 'Units', oldUnits );end % getLabelExtent%-------------------------------------------------------------------------%function updateFont()% Update the rotated text fonts when the axes font changesproperties = {'FontName''FontSize''FontAngle''FontWeight''FontUnits'};propertyValues = get( ax, properties );textLabels = findall( ax, 'Tag', 'RotatedXTickLabel' );set( textLabels, properties, propertyValues );end % updateFontfunction updateAlignment()textLabels = findall( ax, 'Tag', 'RotatedXTickLabel' );angle = get( textLabels(1), 'Rotation' );% Depending on the angle, we may need to change the alignment. We change% alignments within 5 degrees of each 90 degree orientation.if strcmpi( get( ax, 'XAxisLocation' ), 'Top' )if 0 <= angle && angle < 5set( textLabels, 'HorizontalAlignment', 'Center', 'VerticalAlignment', 'Bottom' );elseif 5 <= angle && angle < 85set( textLabels, 'HorizontalAlignment', 'Left', 'VerticalAlignment', 'Bottom' );elseif 85 <= angle && angle < 95set( textLabels, 'HorizontalAlignment', 'Left', 'VerticalAlignment', 'Middle' );elseif 95 <= angle && angle < 175set( textLabels, 'HorizontalAlignment', 'Left', 'VerticalAlignment', 'Top' );elseif 175 <= angle && angle < 185set( textLabels, 'HorizontalAlignment', 'Center', 'VerticalAlignment', 'Top' );elseif 185 <= angle && angle < 265set( textLabels, 'HorizontalAlignment', 'Right', 'VerticalAlignment', 'Top' );elseif 265 <= angle && angle < 275set( textLabels, 'HorizontalAlignment', 'Right', 'VerticalAlignment', 'Middle' );elseif 275 <= angle && angle < 355set( textLabels, 'HorizontalAlignment', 'Right', 'VerticalAlignment', 'Bottom' );else % 355-360set( textLabels, 'HorizontalAlignment', 'Center', 'VerticalAlignment', 'Bottom' );endelseif 0 <= angle && angle < 5set( textLabels, 'HorizontalAlignment', 'Center', 'VerticalAlignment', 'Top' );elseif 5 <= angle && angle < 85set( textLabels, 'HorizontalAlignment', 'Right', 'VerticalAlignment', 'Top' );elseif 85 <= angle && angle < 95set( textLabels, 'HorizontalAlignment', 'Right', 'VerticalAlignment', 'Middle' );elseif 95 <= angle && angle < 175set( textLabels, 'HorizontalAlignment', 'Right', 'VerticalAlignment', 'Bottom' );elseif 175 <= angle && angle < 185set( textLabels, 'HorizontalAlignment', 'Center', 'VerticalAlignment', 'Bottom' );elseif 185 <= angle && angle < 265set( textLabels, 'HorizontalAlignment', 'Left', 'VerticalAlignment', 'Bottom' );elseif 265 <= angle && angle < 275set( textLabels, 'HorizontalAlignment', 'Left', 'VerticalAlignment', 'Middle' );elseif 275 <= angle && angle < 355set( textLabels, 'HorizontalAlignment', 'Left', 'VerticalAlignment', 'Top' );else % 355-360set( textLabels, 'HorizontalAlignment', 'Center', 'VerticalAlignment', 'Top' );endendend%-------------------------------------------------------------------------%function onAxesFontChanged( ~, ~ )updateFont();repositionAxes( ax );repositionXLabel( ax );end % onAxesFontChanged%-------------------------------------------------------------------------%function onAxesPositionChanged( ~, ~ )% We need to accept the new position, so remove the appdata before% redrawingif isappdata( ax, 'OriginalAxesPosition' )rmappdata( ax, 'OriginalAxesPosition' );endif isappdata( ax, 'OriginalXLabelPosition' )rmappdata( ax, 'OriginalXLabelPosition' );endrepositionAxes( ax );repositionXLabel( ax );end % onAxesPositionChanged%-------------------------------------------------------------------------%function onXAxisLocationChanged( ~, ~ )updateAlignment();repositionAxes( ax );repositionXLabel( ax );end % onXAxisLocationChanged%-------------------------------------------------------------------------%function onAxesLimitsChanged( ~, ~ )% The limits have moved, so make sure the labels are still oktextLabels = findall( ax, 'Tag', 'RotatedXTickLabel' );xlim = get( ax, 'XLim' );pos = [0 getYPositionToUse( ax )];for tt=1:numel( textLabels )xval = get( textLabels(tt), 'UserData' );pos(1) = xval;% If the tick is off the edge, make it invisibleif xval<xlim(1) || xval>xlim(2)set( textLabels(tt), 'Visible', 'off', 'Position', pos )elseif ~strcmpi( get( textLabels(tt), 'Visible' ), 'on' )set( textLabels(tt), 'Visible', 'on', 'Position', pos )else% Just set the positionset( textLabels(tt), 'Position', pos );endendrepositionXLabel( ax );end % onAxesPositionChanged%-------------------------------------------------------------------------%function onTextLabelDeleted( ~, ~ )% The final text label has been deleted. This is likely from a% "cla" or "close" call, so we should remove all of our dirty% hacks.restoreDefaultLabels(ax);end%-------------------------------------------------------------------------%function addListeners( ax )% Create listeners. We store the array of listeners in the axes to make% sure that they have the same life-span as the axes they are listening to.axh = handle( ax );listeners = [handle.listener( axh, findprop( axh, 'FontName' ), 'PropertyPostSet', @onAxesFontChanged )handle.listener( axh, findprop( axh, 'FontSize' ), 'PropertyPostSet', @onAxesFontChanged )handle.listener( axh, findprop( axh, 'FontWeight' ), 'PropertyPostSet', @onAxesFontChanged )handle.listener( axh, findprop( axh, 'FontAngle' ), 'PropertyPostSet', @onAxesFontChanged )handle.listener( axh, findprop( axh, 'FontUnits' ), 'PropertyPostSet', @onAxesFontChanged )handle.listener( axh, findprop( axh, 'OuterPosition' ), 'PropertyPostSet', @onAxesPositionChanged )handle.listener( axh, findprop( axh, 'XLim' ), 'PropertyPostSet', @onAxesLimitsChanged )handle.listener( axh, findprop( axh, 'YLim' ), 'PropertyPostSet', @onAxesLimitsChanged )handle.listener( axh, findprop( axh, 'XAxisLocation' ), 'PropertyPostSet', @onXAxisLocationChanged )];setappdata( ax, 'RotateXLabelsListeners', listeners );end % addListeners%-------------------------------------------------------------------------%function removeListeners( ax )% Rempove any property listeners whilst we are fiddling with the axesif isappdata( ax, 'RotateXLabelsListeners' )delete( getappdata( ax, 'RotateXLabelsListeners' ) );rmappdata( ax, 'RotateXLabelsListeners' );endend % removeListeners%-------------------------------------------------------------------------%function y = getYPositionToUse( ax )% Use the direction and XAxisLocation properties to work out which% Y-value to draw the labels at.whichYLim = 1;% If YDir is reversed, switch where we positionif strcmpi( get( ax, 'YDir' ), 'Reverse' )whichYLim = 3-whichYLim;end% If set to "top", then switch (again?)if strcmpi( get( ax, 'XAxisLocation' ), 'Top' )whichYLim = 3-whichYLim;end% Now get the valueylim = get( ax, 'YLim' );y = ylim(whichYLim);end % getYPositionToUseend % EOF