访问 TikZ 中的样式属性?

访问 TikZ 中的样式属性?

可能重复:
如何从 pgfkeys 样式元素中提取值

假设我已经定义了以下 TikZ 样式:

\tikzset{
  mystyle/.style={draw, fill=green, node distance=3mm}
}

我想要绘制以下图片:

在此处输入图片描述

为了绘制这个,我使用了以下代码:

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{calc, positioning}

\begin{document}
\begin{tikzpicture}[%
    mystyle/.style={draw, node distance=3mm}
  ]
  \node [mystyle] (n1) {1};
  \node [mystyle, right=of n1] (n2) {2};
  \node at ([yshift=-3mm] $(n1.south) !0.5! (n2.south)$) [mystyle, below] (n3) {3};
\end{tikzpicture}
\end{document}

虽然它可以工作,但它的问题在于距离(3mm)被定义了两次——一次在样式中,一次在图形本身中。

之前,我通过创建一个定义距离的新维度寄存器来解决这个问题,但是我希望能够直接从样式中提取值。例如,我想要这样的东西:

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{calc, positioning}

\begin{document}
\begin{tikzpicture}[%
    mystyle/.style={draw, node distance=3mm}
  ]
  \node [mystyle] (n1) {1};
  \node [mystyle, right=of n1] (n2) {2};
  \node at ([yshift=-\styleproperty{mystyle/node distance}] $(n1.south) !0.5! (n2.south)$) [mystyle, below] (n3) {3};
\end{tikzpicture}
\end{document}

这可能实现吗?

答案1

感谢 Ryan Reich 最出色的 PGFKeys 跟踪包(位于我如何调试 pgfkeys?),我发现该密钥node distance将其值存储在宏中\tikz@node@distance。这意味着它无法通过 pgfkeys 的“标准通道”(即\pgfkeyvalueof)访问。此外,由于宏名称@中包含 s,因此无法按原样使用它。所以我们必须定义一个包装器来获取此宏的值。

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc,positioning}

% This bit was how I found out what was going on
%\usepackage{trace-pgfkeys}

%\pgfkeystracelevel{verbose}
%\tikzset{node distance=3mm}
%\pgfkeystracelevel{silent}

\makeatletter
\def\getnodedistance{\tikz@node@distance}
\makeatother

\begin{document}

\begin{tikzpicture}[%
    mystyle/.style={draw, node distance=3mm}
  ]
  \node [mystyle] (n1) {1};
  \node [mystyle, right=of n1] (n2) {2};
  \node [mystyle, below] at ([yshift=-\getnodedistance]$(n1.south) !0.5! (n2.south)$) (n3)
        {3};
\end{tikzpicture}
\end{document}

这种方法不容易推广,但那是因为pgfkeys他们可以对传递的值做任何他们想做的事情,包括将它们存储在任意宏中。有时你很幸运,他们会将它们存储在键中,在这种情况下这\pgfkeysvalueof{full key name}就是你想要的。如果使用通用宏,那么你必须使用该宏来访问它。

(另一种方法是向原始键调用添加一些代码,以将值存储在可以使用的另一个宏中。如果键以某种非平凡的方式使用参数,从而难以提取原始值,我会使用此方法。)

注意:由于作业node distance=3mm当地的,您需要确保在调用宏mystyle之前调用该键。这就是我将部分移至坐标计算之前的原因。如果您希望能够在文档中更早地指定,我会以另一种方式完成所有操作:将存储在单独的键中,然后让和访问此键。类似于:\getnodedistance[mystyle,below]3mm3mmnode distanceyshift

\tikzset{
   my global node distance/.initial=3mm,
   mystyle/.style={
      draw,
      node distance=\pgfkeysvalueof{/tikz/my global node distance}
   }
}

...

\node [mystyle,below] at ([yshift=-\pgfkeysvalueof{/tikz/my global node distance]...

编辑(打击乐手):

以下是在样式声明中包含宏赋值的另外两种方法

1)提供一个长度宏名选项,将节点距离的值直接保存到该宏名中(在本例中mynodedist)。

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc,positioning}
\makeatletter
\tikzset{ mystyle/.style={draw, node distance=3mm, save node distance to=mynodedist},
save node distance to/.code={\expandafter\newdimen\csname#1\endcsname%
\advance\csname#1\endcsname by \tikz@node@distance }
}
\makeatother

\begin{document}
\begin{tikzpicture} 
  \node [mystyle] (n1) {1};
  \node [mystyle, right=of n1] (n2) {2};
  \node [mystyle, below] at ([yshift=-\mynodedist ]$(n1.south) !0.5! (n2.south)$) (n3) {3};
\end{tikzpicture}
\end{document}

2)您可以对同一组键进行常规style=code=分配,以实现更规范的键值配对,这归结为仅修改

\makeatletter
\tikzset{ mystyle/.style={draw, node distance=3mm},
mystyle/.add code={}{\def\mynodedist{\tikz@node@distance}}
}
\makeatother

答案2

这个问题很有趣,因为 Andrew 和 percusse 给出了关于 的有趣信息\tikz@node@distance。我认为在这种情况下没有必要直接从样式中提取值。如何提取很有趣,但最好避免这样做,因为 TikZ 为您提供了所有工具。

我不太喜欢定位库,但如果你使用它,我认为更好的方法是一直使用它直到代码结束。node distance在这种情况下,你想使用当前的值,我认为below=of更可取!(而不是yshift

我认为下一个代码给出了你想要实现的目标

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc, positioning}

\begin{document}

\begin{tikzpicture}[%
    every node/.style = {draw}, 
    node distance     = 3mm
    ]
  \node  (n1) {1};
  \node [right=of n1] (n2) {2};
  \path let \p1 = ($(n1.south) !0.5! (n2.south)$) in node[below=of \p1] (n3)  {3};
  % more simpler : \node[below= of $(n1.south) !0.5! (n2.south)$] (n3) {3}; % (percusse)
 \end{tikzpicture} 

\end{document} 

在此处输入图片描述

相关内容