Changing the marker shape or aspect ratio in a legend
6 Ansichten (letzte 30 Tage)
Ältere Kommentare anzeigen
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!
0 Kommentare
Akzeptierte Antwort
DGM
am 20 Jun. 2023
Bearbeitet: DGM
am 20 Jun. 2023
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 Kommentare
DGM
am 22 Jun. 2023
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
Weitere Antworten (0)
Siehe auch
Kategorien
Mehr zu Legend finden Sie in Help Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!