![基本解决方案](https://linux22.com/image/272478/%E5%9F%BA%E6%9C%AC%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88.png)
我有一个使用 绘制的图形tikz
。我正在尝试添加一个图例,它由两种具有不同含义的箭头组成。我的问题是如何在带有箭头的节点之间添加正确的垂直空间。
在 MWE 中,我有一个参考节点,其中的文本由 分隔\\
。如何用箭头对齐节点,后者保持节点(n2)
和(n3)
内的文本之间的垂直空间相同(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}
答案1
基本解决方案
该解决方案提供了两个密钥:
line
和line default font
。
该键接受带或不带line
的参数。如果给出了冒号,则该值将简单地转发到内部键,该键使用冒号之前的部分作为字体参数(希望设置正确)。 之后的部分是行号,即底线。:
:
@line
\baselineskip
:
1
冒号是否存在,其值line default font
将被转发到@line
并将用作字体参数。
代码
\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
\advance\pgfutil@tempcnta-1\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};
\tikzset{line default font=\small, radius=.6pt}
\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}
输出
完善的解决方案
该解决方案包括:
save baseline
在宏中保存\baselineskip
节点末尾的长度的键(在样式中包含这种样式可能会有所帮助)every node
;以键的形式添加到显式节点坐标系中
line
(它检查是否save baseline
已在节点上使用);以及隐式节点坐标的补充。线与锚点之间由字符分隔
'
(不能使用:
或,
,但可以.
再次使用)。
无法line
在没有锚点的情况下使用键(无论是隐式还是显式)。这个问题可以修复。我建议不要'
在节点名称中使用(特别是如果可以'
在没有锚点的情况下使用该线)。
缺点
不要變身!
说真的,如果节点旋转了,或者使用线锚的路径旋转了,或者其中一个scale
ings 处于活动状态,那么我无法保证任何事情。
代码
\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}{%
line/.store in=\tikz@cs@line,% addition
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
\advance\pgfutil@tempcnta-1\relax
\pgfutil@tempdima=\csname pgf@sh@bls@\tikz@cs@node\endcsname
\pgfpointadd{\pgfpointanchor{\tikz@cs@node}{\tikz@cs@angle}}
{\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
\advance\pgfutil@tempcnta-1\relax
\pgfutil@tempdima=\csname pgf@sh@bls@#1\endcsname
\pgfpointadd{\pgfpointanchor{#1}{#2}}
{\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};
\tikzset{radius=.6pt}
\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}