EDIT 2 (Feb 20): New question (hopefully clearer)
With pgfplots
it's possible to obtain "inner" and "outer" figure legend (see Paul Gessler's answer) as:
I would like to achieve the same result with a "simple" Tikz picture (i.e. not a plot).
Currently, thanks to this answer or John Kormylo's anwser below, I am able to create a legend with a Tikzpicture positionned with current bounding box.south east
(see MWE at the end):
So, positionning with current bounding box.south east
is equivalent to the "outer" positionning with pgfplots
.
How can I achieve the equivalent to the "inner" positionning with the legend in the previous figure and without using an absolute shift (i.e. [yshift=.., xshift=..]
) but using something like pos=
inner
current bounding box.south east
instead?
I specify that the way the legend is built in my MWE is not limiting, that is to say that I am open to other ways of creating a legend (with scope
, path
,...) if that makes "inner" positioning possible.
EDIT 3 (Feb 24): First attempt
Thanks to Ulrike Fischer comment below, I get this (which is very closed to my needs):
The last problem is a legend overlap with the node. I wonder if I can detect or access to the legend
node height in order to plot the legend
node with a yshift
equal to its height (because the legend could be a multiline matrix).
Thanks to percusse answer here I'm able to obtain this:
Where, the "bleu legend" is the final result I would like to obtain. The "black legend" was used only to determine the legend
node height and I would like to delete it...
The red text and line show the lenght of the yshit
stored in \mytemp
and corresponding to the legend
node height.
How can I remove the black legend after determining its height?
Or any other idea to automatically set the yshift
in order to avoid overlaping?
And the MWE:
\documentclass[tikz=true,crop=true,class=minimal,border=1pt,10pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning}
\begin{document}
\begin{tikzpicture}
\begin{scope}[local bounding box=localbox]
% NODES
\node (n1) [draw, text width=5em, minimum height=8em] {node 1};%
% ARROWS
\coordinate[above right=of n1.east] (aux2a);
\coordinate[below right=of n1.east] (aux2b);
%
\draw[-latex] (aux2a -| n1.east)
to (aux2a) node[right] {short label};
\draw[-latex] (aux2b -| n1.east)
to (aux2b) node[right] {a bit longer label};
\end{scope}
% LEGEND
% First black Legend
\path (localbox.north west)%
node[name=legend,matrix,anchor=west,cells={nodes={font=\sffamily,anchor=west}},
draw,thick,inner sep=0.3ex]{%
\draw[-latex](0,0) -- ++ (0.6,0); & \node{arrow};\\
};%
% Access to black legend node height
\pgfpointdiff{\pgfpointanchor{legend}{south west}}{\pgfpointanchor{legend}{north west}}
\pgfmathsetmacro\mytemp{\csname pgf@y\endcsname}
\draw[red] ([xshift=1mm]legend.north east) -- ++(0pt,\mytemp pt)
node[midway,right] {\mytemp pt};
% Final blue legend
\path ([yshift=\mytemp pt]localbox.north west)%
node[name=legend,matrix,anchor=west,cells={nodes={font=\sffamily,anchor=west}},
draw,thick,inner sep=0.3ex,draw=blue!80]{%
\draw[-latex](0,0) -- ++ (0.6,0); & \node{arrow};\\
};%
\end{tikzpicture}
\end{document}
EDIT 4: Second attempt
Here is my ugly but "working" solution.
If there is NO overlapping, the legend is just polted with (using a scope:
local bounding box=localbox
)\path (localbox.south east) node[name=legend,anchor=
west
...
If there is overlapping (the legend is shifted reagarding to it's own size):
First, a temporary legend node is plotted at (0,0) coodinate:
Second, the size (widht and height) of this legend is extracted (thanks to percusse answer here).
Third, the temporary legend is entirely hide by a white rectangle:
\node (whiterec) [rectangle,fill=white,draw=white,minimum height=\mytemp pt,minimum width=\legendwidth pt] at (legend){};
Fourth, the content of the Tikzpicture is plotted.
Fifth, the final legend is plotted and shifted regarding the size of the remporary legend (here an exemple at north west):
The MWE:
\documentclass[tikz=true,crop=true,class=minimal,border=1pt,10pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning,calc}
\begin{document}
\begin{tikzpicture}
\begin{scope}[local bounding box=localbox]
% First temporary black Legend
\path (0,0)%
node[name=legend,matrix,anchor=west,cells={nodes={font=\sffamily,anchor=west}},
draw,thick,inner sep=0.3ex]{%
\draw[-latex](0,0) -- ++ (0.6,0); & \node{arrow};\\
};%
% Access to black legend node height and width
\pgfpointdiff{\pgfpointanchor{legend}{south west}}{\pgfpointanchor{legend}{north west}}%
\pgfmathsetmacro\legendheight{\csname pgf@y\endcsname}
\pgfpointdiff{\pgfpointanchor{legend}{west}}{\pgfpointanchor{legend}{east}}%
\pgfmathsetmacro\legendwidth{\csname pgf@x\endcsname}%
% NODES
\node (whiterec) [rectangle,fill=white,draw=white,minimum height=\legendheight pt,minimum width=\legendwidth pt] at (legend){};
\node (n1) [draw, text width=5em, minimum height=8em] {node 1};%
% ARROWS
\coordinate[above right=of n1.east] (aux2a);
\coordinate[below right=of n1.east] (aux2b);
%
\draw[-latex] (aux2a -| n1.east)
to (aux2a) node[right] {short label};
\draw[-latex] (aux2b -| n1.east)
to (aux2b) node[right] {a bit longer label};:
% LEGEND
% Final blue legend
\path ([yshift=\legendheight/2 pt+1pt]localbox.north west)%
node[name=legend,matrix,anchor=west,cells={nodes={font=\sffamily,anchor=west}},
draw,thick,inner sep=0.3ex,draw=blue!80]{%
\draw[-latex](0,0) -- ++ (0.6,0); & \node{arrow};\\
};%
\end{scope}%
\end{tikzpicture}
\end{document}
The question is, is there a way to simplify this method?
For exemple, is it possible to acces the legend size witouht "plotting" it first and after hiding it?
Old question (unclear)
Thanks to this answer I am able to plot a legend like this with a Tikzpicture (the legend is in the bottom right corner in the figure below, placed with \path(current bounding box.south east)
, see MWE at the end):
But I would prefer this result (warning: red things are not wanted in the final result, it is just for explanation purpose):
Start EDIT 1.1 In other words, I would like to place the legend with something equivalent to (current bounding box.south east)
but not starting relatively from the south east
of the bounding box
but from the south east
"inside of the picture borders" instead (green coordinates in the following figure). (BTW I'm not sure the red lines reflect the real behaviour and coordinates when unsing (current bounding box.south east)
)
End EDIT 1.1
Another exemple of expected result would be, with a bigger node:
Or this (with something like north east
):
- Is there a way to obtain this behaviour automatically by using someting like
(current
"limits
"box.south east)
? - If yes, it is also possible to choose the minimal vertical distance represented by the
ymin
in the figure above (which could take negative values):\path([ymin=-5mm]current limits box.south east)
? - If yes, it is also possible to choose also a minimal horizontal distance
xmin
like this:
The MWE:
\documentclass[tikz=true,crop=true,class=minimal,border=1pt,10pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning}
\begin{document}
\begin{tikzpicture}
% NODES
\node (n1) [draw, text width=5em, minimum height=8em] {node 1};%
% ARROWS
\coordinate[above right=of n1.east] (aux2a);
\coordinate[below right=of n1.east] (aux2b);
%
\draw[-latex] (aux2a -| n1.east)
to (aux2a) node[right] {short label};
\draw[-latex] (aux2b -| n1.east)
to (aux2b) node[right] {a bit longer label};
% LEGEND
\path (current bounding box.south east)%
node[matrix,anchor=north west,cells={nodes={font=\sffamily,anchor=west}},
draw,thick,inner sep=0.3ex]{%
\draw[-latex](0,0) -- ++ (0.6,0); & \node{arrow};\\
};%
\end{tikzpicture}
\end{document}
Start EDIT 1.2 Why I want that?
Auto-positionning of the legend "inside the image limits" would allow very fast positionning with compact picture by just giving a ymin
in order to be sure to not overlap anything with the legend.
This "clever" behaviour would allow the possibility to better automate the picture generation by adding the legend automaticaly and set, for e.g. ymin=1mm
and xmin=1mm
to prevent any overlaping problem.
End EDIT 1.2
\begin{scope}[local bounding box=name] ... \end{scope}
to create named boxes.scope
in the picture. In order to be sure I well understand your comment, your are proposing to use\begin{scope}[local bounding box=name] ... \end{scope}
instead of\path (current bounding box.south east)...
for the legend "block" only right?(current bounding box.south east)
useanchor=north east
.