advanced plotting (legend manipulation) in Matlab

2019-09-14 15:51发布

I want to add a legend to my plot so that it look as in the picture (reduce the length of the line and suppress unnecessary spaces)

enter image description here

x = randn(6,20);

figure(2)
hax = gca;

plot(x(1,:),'--k','linewidth',1.5);
hold on;
plot(x(2,:),'b','linewidth',1.5);
hold on;
plot(x(3,:),'g','linewidth',1.5);
hold on;
plot(x(4,:),'r','linewidth',1.5);
hold on;
plot(x(5,:),'c','linewidth',1.5);
hold on;
plot(x(6,:),':r','linewidth',1.5);


ylabel('states','fontsize',14); xlabel('time(s)','fontsize',14);
legend('True','SCKS(h1)','SCKS(h2)','SCKS(h3)','SCKS(h4)','DEM',14);
legendshrink(0.8,[]);
%Fig_legend = legend('Taylor','Euler','LLscheme','LLscheme1');
%set(Fig_legend,'FontSize',7)

grid(hax,'on')
axis(hax,'tight')
set(hax,'box','on','Layer','top');
set(hax,'tickdir','out')

is there anyone can help me?

标签: matlab legend
1条回答
\"骚年 ilove
2楼-- · 2019-09-14 16:35

As reported in the MatLab online documentation Starting in R2014b, colorbars and legends are no longer axes objects.

This limits the possibilites to work on the legend in order to achieve your target.

A possible solution could be to create a your own axes based legend following these steps:

  • create the legend calling the legend function with the following syntax [lgd,icons,plots,txt] = legend(___) (notice, this syntax is not recommended nevertheless, we are going to delete the legend in the next steps, so it will not be a problem)
  • get the position of the legend
  • identify the number of items in the legend

    • for each line in the graph there are three items in the legend (the line, the marker and the text)
    • in the case of six line in a graph the legend handle will contains 18 objects in the following order:

      • 6 x handles to text
      • for each of the 6 lines
        • 1 handle to the line
        • 1 handle to the marker
  • get the data of the items in the legend:
    • line data: XData, YData, Color, 'LineStyle`
    • text data: string, position
  • delete the original legend
  • add an axes to the figure with position and size equal to the original legend
  • plot on this axes the lines that will represent the legend (you've got the data on the previous steps)
  • to shrink the lines, just reduce reduce the value of the second element of XData
  • add the legend text correspinding to the line (with the text function. Since in the previous step you've recuced the lengt of the lines you've to move on the left the text
  • reduce the size of the axes:
    • you can use the Extent property of the text items to identify the length of the longer one
    • then add to it the length of the corresponding line
  • update the axes position (its width) with the value caomputed in the above step

This is a possible implementation (based on you code):

x = randn(6,20);

figure(2)
hax = gca;

plot(x(1,:),'--k','linewidth',1.5);
hold on;
plot(x(2,:),'b','linewidth',1.5);
% hold on;
plot(x(3,:),'g','linewidth',1.5);
% hold on;
plot(x(4,:),'r','linewidth',1.5);
% hold on;
plot(x(5,:),'c','linewidth',1.5);
% hold on;
plot(x(6,:),':r','linewidth',1.5);


ylabel('states','fontsize',14); xlabel('time(s)','fontsize',10);
%legend('True','SCKS(h1)','SCKS(h2)','SCKS(h3)','SCKS(h4)','DEM',14);
%
% New call "legend"
%
[leg_h,leg_item_h,~,~]=legend('True','SCKS(h1)','SCKS(h2)','SCKS(h3)','SCKS(h4)','DEM',14);
%
% legendshrink(0.8,[]);
%Fig_legend = legend('Taylor','Euler','LLscheme','LLscheme1');
%set(Fig_legend,'FontSize',7)

grid(hax,'on')
% axis(hax,'tight')
set(hax,'box','on','Layer','top');
set(hax,'tickdir','out')

%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% GENERATION OF THE LEGEND %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Define a scale factor fot the lines
line_scale_factor=1.4;
% Define a scale factor fot the lines
text_scale_factor=1.35;
% Get the "Position" of the legend
orig_leg_pos=get(leg_h,'position')
% Get the number on objects in the legend
n_obj=length(leg_item_h);
% Extract the "Line" object
line_obj=leg_item_h(n_obj/3+1:2:n_obj);
% Get the "LineStyle" of each "Line" in the legend
l_style=get(line_obj,'LineStyle')
% Get the "Color" of each "Line" in the legend
l_col=cell2mat(get(line_obj,'color'))
% Get the "XData" and "YData" of the "Lines" in the legend
leg_x_data=cell2mat(get(line_obj,'xdata'))
leg_y_data=cell2mat(get(line_obj,'ydata'))
% Get the handle of the "Text" of the items in the legend
leg_t=leg_item_h(1:n_obj/3)
% Get the "Text" of the items in the legend
str=get(leg_t,'string')
% Get the "Position" of each "Text" item in the legend
tx=cell2mat(get(leg_t,'position'))
% Delete the original legend
delete(leg_h)
% Create an axes with the same position and size of the original legend
ax=axes('position',orig_leg_pos,'xlim',[0 1],'ylim',[0 1], ...
   'xtick',[],'ytick',[],'box','on')
hold on
% Add the legend items to the axes
for i=1:n_obj/3
   % Add the lines with the original settings (color, style, ...)
   plot([leg_x_data(i,1) leg_x_data(i,2)/line_scale_factor],leg_y_data(i,:),'color',l_col(i,:), ...
                          'linestyle',l_style{i}, ...
                          'linewidth',1.4)
   % Add the text
   th(i,:)=text(leg_x_data(i,2)/text_scale_factor,tx(i,2),0,str{i},'fontsize',9, ...
           'unit','normalized')
end
% Get the maximun extent of the lagend "Text"
tx_max_ext=max(reshape([th(:).Extent],4,6)');
% Evaluate the axis scaling factor
tx_r_1=tx_max_ext(3)+leg_x_data(i,2)/line_scale_factor
% Get the axes position
axp=ax.Position
% Resize the axes width
ax.Position=[axp(1) axp(2) axp(3)*tx_r_1 axp(4)]

enter image description here

Hope this helps,

Qapla'

查看更多
登录 后发表回答