将不存在的条目添加到图例

Add non-existent entry to legend

我想手动添加一个条目到 MATLAB 图例中。此图例可以预先存在并包含其他图形元素的条目,但不一定。

我制作了一个散点图,但没有使用例如scatter(x,y),我使用

绘制它
for n = 1:numel(x)
    text(x(n),y(n),num2str(n), ...
    'HorizontalAlignment','center','color',[1 0 0])
end

这会生成数字 1 到 x(和 y 中的元素数)的散点图,因为它们的大小相同。我想为这些数字添加图例条目。

我尝试使用

添加或编辑图例
[h,icons,plots,s] = legend(___)

legend documentation page 所述。我不知道如何添加图例条目,而不必绘制某些东西(例如实际的散点图或常规图)。我希望图例中常用的线条或标记符号是数字或字符,例如'n',表示图中的数字。这可能吗?如何实现?

埃里克编辑

我的答案低于 zelanix 的答案,因为我的答案是基于它的。


原回答

一个相当可行的解决方案可能如下:

x = rand(10, 1);
y = rand(10, 1);

figure;

text(x,y,num2str(transpose(1:numel(x))),'HorizontalAlignment','center')

% Create dummy legend entries, with white symbols.
hold on;
plot(0, 0, 'o', 'color', [1 1 1], 'visible', 'off');
plot(0, 0, 'o', 'color', [1 1 1], 'visible', 'off');
hold off;

% Create legend with placeholder entries.
[h_leg, icons] = legend('foo', 'bar');

% Create new (invisible) axes on top of the legend so that we can draw
% text on top.
ax2 = axes('position', get(h_leg, 'position'));
set(ax2, 'Color', 'none', 'Box', 'off')
set(ax2, 'xtick', [], 'ytick', []);

% Draw the numbers on the legend, positioned as per the original markers.
text(get(icons(4), 'XData'), get(icons(4), 'YData'), '1', 'HorizontalAlignment', 'center')
text(get(icons(6), 'XData'), get(icons(6), 'YData'), '2', 'HorizontalAlignment', 'center')

axes(ax1);

输出:

这样做的诀窍在于,新轴是在与图例完全相同的位置创建的,icons 元素的坐标是标准化坐标,现在可以在新坐标中使用轴直接。当然,您现在可以自由使用任何字体大小/颜色/任何您需要的东西。

缺点是只有在您的图例被填充和定位后才能调用它。移动图例或添加条目不会更新自定义标记。


埃里克的回答

基于 zelanix 上面的回答。这是一个正在进行中的答案,我正在尝试为此提供一个非常灵活的功能。目前,它只是一个脚本,您需要根据自己的情况进行调整。

% plot some lines and some text numbers
f = figure;
plot([0 1],[0 1],[0 1],[1 0])
x = rand(25,1);
y = rand(25,1);
for n = 1:numel(x)
    text(x(n),y(n),num2str(n), ...
    'HorizontalAlignment','center','color',[1 0 0])
end
hold on
% scatter(x,y) % used to test the number positions
scatter(x,y,'Visible','off') % moves the legend location to best position

% create the dummy legend using some dummy plots
plot(0,0,'o','Visible','off')
[l,i] = legend('some line','some other line','some numbers','location','best');
l.Visible = 'off';

% create empty axes to mimick legend
oa = gca; % the original current axes handle
a = axes;
axis manual
a.Box = 'on';
a.XTick = [];
a.YTick = [];

% copy the legend's properties and contents to the new axes
a.Units = l.Units; % just in case
a.Position = l.Position;
i = copyobj(i,a);

% replace the marker with a red 'n'
s = findobj(i,'string','some numbers');
% m = findobj(i(i~=s),'-property','YData','marker','o');
m = findobj(i(i~=s),'-property','YData');
sy = s.Position(2);
if numel(m)>1
    dy = abs(m(1).YData - sy);
    for k = 2:numel(m)
        h = m(k);
        dy2 = abs(h.YData - sy);
        if dy2<dy
            kbest = k;
            dy = dy2;
        end
    end
    m = m(kbest);
end
m.Visible = 'off';
mx = m.XData;
text(mx,sy,'n','HorizontalAlignment','center','color',[1 0 0])

% reset current axes to main axes
f.CurrentAxes = oa;

结果: