问题
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)
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?
回答1:
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
, themarker
and thetext
) 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
- 6 x handles to
- for each line in the graph there are three items in the legend (the
- get the data of the items in the legend:
- line data:
XData
,YData
,Color
, 'LineStyle` - text data:
string
,position
- line data:
- 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 thetext
items to identify the length of the longer one - then add to it the length of the corresponding line
- you can use the
- update the
axes
position (itswidth
) 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)]
Hope this helps,
Qapla'
来源:https://stackoverflow.com/questions/42740907/advanced-plotting-legend-manipulation-in-matlab