# Nodes vertical distance in a legend of a tikzpicture

I have a figure drawn using tikz. I am trying to add a legend, which consists in two types of arrows with different meanings. My problem is how to add the correct vertical space between the nodes with arrows.

In the MWE, I have the a reference node and the text within it is separated by \\. How can I align the nodes with arrows with latter keeping the same vertical space between the text of nodes (n2) and (n3) as within (n1)?

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{calc}

\begin{document}
\begin{tikzpicture}
\node[align=right,inner ysep=0pt] (n1) {BLA\\ BLB};
\draw[->,red,align=center] ($(n1.north east)+(1cm,0cm)$) -- ++(0:8pt) node[at end,anchor=west] (n2) {BLA BLA};
\draw[<-,red] ($(n1.north east)+(1cm,-\baselineskip)$) -- ++(0:8pt) node[at end,anchor=west] (n3) {BLA BLB};
\end{tikzpicture}
\end{document}
-

# Basic solution

This solution provides two keys:

• line and
• line default font.

The line key accepts its argument either with : or without :. If the colon is given, the value is simply forwarded to the internal @line key which uses the part before the colon as a font argument (which hopefully set \baselineskip correctly. The part after the : is the line number, 1 being the bottom line.

Isn’t the colon present the value of line default font will be forwarded to @line and will be used as the font-argument.

## Code

\documentclass[tikz,convert=false]{standalone}
\makeatletter
\tikzset{
line default font/.initial=\normalsize,
line/.code=\pgfutil@in@{:}{#1}%
\ifpgfutil@in@
\pgfkeysalso{@line={#1}}\else
\pgfkeysalso{@line={\pgfkeysvalueof{/tikz/line default font}:#1}}%
\fi,
@line/.code args={#1:#2}{% internal
\begingroup
#1%
\pgfutil@tempcnta#2\relax
\pgf@xa\pgfutil@tempcnta\baselineskip\relax
\pgfmath@returnone\pgf@xa
\endgroup
\pgftransformshift{\pgfqpoint{0pt}{\pgfmathresult pt}}%
}
}
\begin{document}
\begin{tikzpicture}
\node[align=right, font=\small, draw=lightgray] (n1) {BL\\ BLB};
\draw[->] ([line=\small:2,xshift=1cm] n1.base east) -- ++(0:8pt)
node[at end,anchor=base west] (n2) {Line 2};
\draw[<-] ([line=1,       xshift=1cm] n1.base east) -- ++(0:8pt)
node[at end,anchor=base west] (n3) {Line 1};
\fill ([line=1] n1.base west) circle[]
([line=2] n1.base west) circle[] [red];
\fill ([line=1] n1.base)      circle[]
([line=2] n1.base)      circle[];
\fill ([line=1] n1.text)      circle[]
([line=2] n1.text)      circle[] [blue];
\fill ([line=1] n1.base east) circle[]
([line=2] n1.base east) circle[] [green];
\end{tikzpicture}
\end{document}

# Sophisticated solution

This solution includes:

• the save baseline key that saves the \baselineskip length at the end of the node in a macro (it might be helpful to include this style in the every node style);

• an addition to the explicit node coordinate system in the form of the line key (it checks whether save baseline has been used on the node); and

• an addition to the implicit node coordinate. The line is separated from the anchor by the character ' (it is not possible to use : or ,, it could be possible to use . again).

It is not possible to use the line key without an anchor (implicitly or explicitly). This could be fixed. I advise against using ' in a node name (especially if it should be possible to use the line ' without an anchor).

### Shortcomings

Don’t transform!

Seriously, if either the node is rotated or the path which uses the line-anchor is rotated or one of the scaleings is active I can guarantee nothing.

## Code

\documentclass[tikz,convert=false]{standalone}
\makeatletter
\tikzset{
save baseline/.style={
execute at end node=\expandafter\xdef\csname pgf@sh@bls@\tikz@fig@name\endcsname{\the\baselineskip}
}
}
\pgfqkeys{/tikz/cs}{%
anchor/.store in=\tikz@cs@angle% small fix to reduce the code of the 'node' cs
}
\tikzdeclarecoordinatesystem{node}{%
\tikzset{cs/.cd,name=,anchor=none,line=none,#1}%
\ifx\tikz@cs@angle\tikz@nonetext%
\expandafter\ifx\csname pgf@sh@ns@\tikz@cs@node\endcsname\tikz@coordinate@text%
\else
\aftergroup\tikz@shapebordertrue%
\edef\tikz@shapeborder@name{\tikz@cs@node}%
\fi%
\pgfpointanchor{\tikz@cs@node}{center}%
\else%
\ifx\tikz@cs@line\tikz@nonetext
\pgfpointanchor{\tikz@cs@node}{\tikz@cs@angle}%
\else
\expandafter\ifx\csname pgf@sh@bls@\tikz@cs@node\endcsname\relax
\PackageError{TikZ}{The \tikz@cs@node\space has no saved baseline, use the 'save baseline' option}{}
\pgfpointanchor{\tikz@cs@node}{\tikz@cs@angle}
\else
\pgfutil@tempcnta=\tikz@cs@line\relax
\pgfutil@tempdima=\csname pgf@sh@bls@\tikz@cs@node\endcsname
{\pgfqpoint{0pt}{\pgfutil@tempcnta\pgfutil@tempdima}}%
\fi
\fi
\fi%
}
\def\tikz@calc@anchor#1.#2\tikz@stop{%
\pgfutil@in@{'}{#2}
\ifpgfutil@in@
\expandafter\ifx\csname pgf@sh@bls@#1\endcsname\relax
\PackageError{TikZ}{The #1 has no saved baseline, use the 'save baseline' option}{}
\pgfpointanchor{#1}{#2}
\else
\tikz@calc@anchor@line#1.#2\tikz@stop
\fi
\else
\pgfpointanchor{#1}{#2}%
\fi
}
\def\tikz@calc@anchor@line#1.#2'#3\tikz@stop{%
\pgfutil@tempcnta=#3\relax
\pgfutil@tempdima=\csname pgf@sh@bls@#1\endcsname
{\pgfqpoint{0pt}{\pgfutil@tempcnta\pgfutil@tempdima}}%
}
\makeatother
\begin{document}
\begin{tikzpicture}
\node[align=right, font=\small, draw=lightgray, save baseline] (n1) {BL\\ BLB};
\draw[->] (node cs: name=n1, anchor=base east, line=2) -- ++(0:8pt)
node[at end,anchor=base west] (n2) {Line 2};
\draw[<-] (node cs: name=n1, anchor=base east) -- ++(0:8pt)
node[at end,anchor=base west] (n3) {Line 1};
\fill (n1.base west'1) circle[]
(n1.base west'2) circle[] [red];
\fill (n1.base'1)      circle[]
(n1.base'2)      circle[];
\fill (n1.text'1)      circle[]
(n1.text'2)      circle[] [blue];
\fill (n1.base east'1) circle[]
(n1.base east'2) circle[] [green];
\end{tikzpicture}
\end{document}

## Output

-
Your code doesn't work. It gives l.6 ...[->,red] ([line=2,xshift=1cm] n1.base east) -- ++(0:8pt) ? –  cacamailg Jul 23 '13 at 0:58
The code works now. But the vertical space is correct only if font=\normalsize. Since I am using font=\small for all the nodes, I had to do \tikzset{line/.style={shift={(+0pt,{(#1-1)*\baselineskip*0.91})}}}. This 0.91 is achieved by trial-error tentatives. How can we introduce a factor if font size chances to \small, \footnotesize, etc.? –  cacamailg Jul 23 '13 at 12:00
@cacamailg Yes, that is annoying (and is one of the things I meant with “[i]f \baselineskip is not specifically changed inside the node”). I am afraid there is no easy solution. If you typeset all nodes in \small you could issue \small after \begin{tikzpicture}[…] (which changes also all em and ex dimensions of course). Or you can use ([/utils/exec=\small,line=2,xshift=1cm] n1.base east) (best hidden in another style). If you want to go very sophisticated, you let \baselineskip be stored away and reference it later (could be a special cs). Would this be needed? –  Qrrbrbirlbel Jul 23 '13 at 12:26
Well, all nodes are typeset in \small because of space constraints. That special style that you mention, probably is the best solution, because I don't know if I need to typeset some nodes in \footnotesize. Or change the style that you have defined to include a second parameter. –  cacamailg Jul 23 '13 at 12:37
@cacamailg Please see my update. The “Sophisticated solution” is what I was talking about in my previous comment. But don’t use any transformations (besides shifting I think). This could go horrible wrong (but that's true even for the other solutions). I will take a look into the transformations nonetheless. –  Qrrbrbirlbel Jul 23 '13 at 14:59