Changing the marker shape or aspect ratio in a legend

조회 수: 14 (최근 30일)
z8080
z8080 2023년 6월 20일
댓글: z8080 2023년 6월 22일
Consider the following example code, and the plot legend it creates:
% Example data
means = [10 40 50 60; ...3 groups, each with 4 conditions (measures)
20 50 60 70; ...
30 60 80 90];
SEMs = [1 4 8 6; ...
2 5 9 12; ...
3 6 10 13];
nGroups = size(means, 1);
nConditionsPerGroup = size(means, 2);
figure('Position', [71 433 560 420])
b = bar(means, 'grouped');
hold on
clear x
% Get the x coordinate of the bars
for i = 1:nConditionsPerGroup
x(i,:) = b(i).XEndPoints;
b(i).BarWidth = 1;
end
% Plot the errorbars
errorbar(x',means,SEMs,'k','linestyle','none');
hold off
set(gca, 'XTickLabel', {'Low' 'Middle' 'High'}, 'FontSize', 12);
xlabel('Socio-economic status', 'FontSize', 18)
[leg,att] = legend('A', 'B', 'C', 'D', 'Orientation','horizontal', 'FontSize', 15);
title(leg,'Measures')
leg.Title.Visible = 'off';
box off
ax = gca;
ax.YGrid = 'on';
I'd like to change the aspect ratio of the legend markers to make them square instead of rectangular. Alternatively, to change their shape altogether and make them e.g. round.
However, I found no property inside the legend handle to manipulate aspect ratio or shape of the markers, only their size (`MarkerSize`). Changing the overall size (width/height) of the legend leaves aspect ratio unchanged.
Thanks for any help!

채택된 답변

DGM
DGM 2023년 6월 20일
편집: DGM 2023년 6월 20일
Here's one way. You might also want to adjust the text object positions as well.
% Example data
means = [10 40 50 60; ...3 groups, each with 4 conditions (measures)
20 50 60 70; ...
30 60 80 90];
SEMs = [1 4 8 6; ...
2 5 9 12; ...
3 6 10 13];
nGroups = size(means, 1);
nConditionsPerGroup = size(means, 2);
%figure('Position', [71 433 560 420])
b = bar(means, 'grouped');
hold on
clear x
% Get the x coordinate of the bars
for i = 1:nConditionsPerGroup
x(i,:) = b(i).XEndPoints;
b(i).BarWidth = 1;
end
% Plot the errorbars
errorbar(x',means,SEMs,'k','linestyle','none');
hold off
set(gca, 'XTickLabel', {'Low' 'Middle' 'High'}, 'FontSize', 12);
xlabel('Socio-economic status', 'FontSize', 18)
[leg,att] = legend('A', 'B', 'C', 'D', 'Orientation','horizontal', 'FontSize', 15);
title(leg,'Measures')
leg.Title.Visible = 'off';
box off
ax = gca;
ax.YGrid = 'on';
% adjust each patch object in the legend
% patch vertex data is normalized WRT the legend box
textoffset = att(1).Position(1) - att(5).Children.Vertices(3,1);
leg.Units = 'pixels';
lp = leg.Position;
for k = 1:4
V = att(k+4).Children.Vertices;
xcent = mean(V(2:3,1))*lp(3);
halfw = diff(V(1:2,2))/2*lp(4);
V(:,1) = (xcent + halfw*[-1 -1 1 1 -1].')/lp(3);
att(k+4).Children.Vertices = V;
att(k).Position(1) = V(3,1) + textoffset;
end
Since the objects are just patches, I don't see why you couldn't make them into any polygonal shape you want.
Alternatively, you can also do other workarounds using dummy objects:
  댓글 수: 3
DGM
DGM 2023년 6월 22일
As far as anyone will be able to tell, an appropriate polygon might as well be a circle.
% Example data
means = [10 40 50 60; ...3 groups, each with 4 conditions (measures)
20 50 60 70; ...
30 60 80 90];
SEMs = [1 4 8 6; ...
2 5 9 12; ...
3 6 10 13];
nGroups = size(means, 1);
nConditionsPerGroup = size(means, 2);
%figure('Position', [71 433 560 420])
b = bar(means, 'grouped');
hold on
clear x
% Get the x coordinate of the bars
for i = 1:nConditionsPerGroup
x(i,:) = b(i).XEndPoints;
b(i).BarWidth = 1;
end
% Plot the errorbars
errorbar(x',means,SEMs,'k','linestyle','none');
hold off
set(gca, 'XTickLabel', {'Low' 'Middle' 'High'}, 'FontSize', 12);
xlabel('Socio-economic status', 'FontSize', 18)
[leg,att] = legend('A', 'B', 'C', 'D', 'Orientation','horizontal', 'FontSize', 15);
title(leg,'Measures')
leg.Title.Visible = 'off';
box off
ax = gca;
ax.YGrid = 'on';
% adjust each patch object in the legend
% patch vertex data is normalized WRT the legend box
nsides = 100; % pick any regular polygon
theta = (0:360/nsides:360) + 360/nsides/2;
textoffset = att(1).Position(1) - att(5).Children.Vertices(3,1);
leg.Units = 'pixels';
lp = leg.Position;
for k = 1:4
% replace patch object with a regular polygon
V = att(k+4).Children.Vertices;
patchcent = [mean(V(2:3,1)) mean(V(1:2,2))].*lp(3:4);
radius = diff(V(1:2,2))/2*lp(4);
V = patchcent + radius*[cosd(theta.') sind(theta.')];
V = V./lp(3:4);
att(k+4).Children.Vertices = V;
att(k+4).Children.Faces = 1:numel(theta);
% move text label
att(k).Position(1) = V(3,1) + textoffset;
end
z8080
z8080 2023년 6월 22일
beautiful work!!

댓글을 달려면 로그인하십시오.

추가 답변 (0개)

카테고리

Help CenterFile Exchange에서 Legend에 대해 자세히 알아보기

태그

제품


릴리스

R2023a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by