编辑 TikZ Chains 以添加标签并保留添加单独样式的选项

编辑 TikZ Chains 以添加标签并保留添加单独样式的选项

我发现代码它重新定义了定义链的方式(\chainin),并允许在链中包含标签。但是,此代码禁用了样式选项(bywith关键字)。但是,我需要为每个链赋予单独的样式。

我如何才能为每个链添加单独的样式,同时能够通过添加节点来标记连接,例如:node [left] {tag}。所以我的目标是这样的:\chainin (node) [join=by myStyle, {node [left] {my Tag}}];

\documentclass{standalone}

\usepackage{tikz}
\usetikzlibrary{shapes,chains,scopes,matrix}
% This code makes it able to include the tag
\makeatletter
\tikzset{join/.code=\tikzset{after node path={%
\ifx\tikzchainprevious\pgfutil@empty\else(\tikzchainprevious)%
edge[every join]#1(\tikzchaincurrent)\fi}}}
\makeatother

\begin{document}

\begin{tikzpicture}[auto,
  decision/.style = {draw,
                     diamond,
                     text badly centered,
                     fill          = blue!5,
                     text width    = 15mm,
                     node distance = 2.5cm,
                     inner sep     = 0pt},
  block/.style    = {draw,
                     rectangle,
                     text centered,
                     rounded corners,
                     fill           = blue!5,
                     text width     = 20mm,
                     minimum height = 10mm},
  tip/.style      = {->,
                     very thick,
                     color = black!50}
]

\matrix[row sep=1cm]{
\node [block] (blk) {A block here}; \\
\node [decision] (dec) {Is something?};\\
};

{ [start chain]
  \chainin (blk);
  % By removing the 'by tip' style this compiles
  \chainin (dec) [join=by tip, {node [left] {yes}}];
}
\end{tikzpicture}
\end{document}

答案1

问题是连接未用作参数化样式,但代码已运行。也就是说,by tip, {node [left] {yes}}变为,#1因此join/.code它被放置在之后edge[every join]。这意味着如果没有它,tip它也可以正常工作,节点被放置在边缘之后并按预期应用。问题是您希望将tip作为选项放置在边缘上,除了every join。实现此目的的最简单方法是让join两个参数,一个用于边缘选项,另一个用于表示可能的节点。这可以通过以下代码实现:

\documentclass{standalone}

\usepackage{tikz}
\usetikzlibrary{shapes,chains,scopes,matrix}
% This code makes it able to include the tag
\makeatletter
\tikzset{join/.code 2 args=\tikzset{after node path={%
\ifx\tikzchainprevious\pgfutil@empty\else(\tikzchainprevious)%
edge[every join,#1]#2(\tikzchaincurrent)\fi}}}
\makeatother

\begin{document}

\begin{tikzpicture}[auto,
  decision/.style = {draw,
                     diamond,
                     text badly centered,
                     fill          = blue!5,
                     text width    = 15mm,
                     node distance = 2.5cm,
                     inner sep     = 0pt},
  block/.style    = {draw,
                     rectangle,
                     text centered,
                     rounded corners,
                     fill           = blue!5,
                     text width     = 20mm,
                     minimum height = 10mm},
  tip/.style      = {->,
                     very thick,
                     color = black!50}
]

\matrix[row sep=1cm]{
\node [block] (blk) {A block here}; \\
\node [decision] (dec) {Is something?};\\
};

{ [start chain]
  \chainin (blk);
  %tip and node:
  \chainin (dec) [join={tip}{node [left] {yes}}];
  %Only the tip:
  %\chainin (dec) [join={tip}{}];
  %Only the node:
  %\chainin (dec) [join={}{node [left] {yes}}];
}
\end{tikzpicture}
\end{document}

如您所见,如果您不想要连接的特定部分,则可以将参数留空。

编辑:我看不出有办法实现这一点。因为你必须改变code键的join才能获得所需的行为。但要获得with .. by ...行为,需要不同的代码。不幸的是,据我所知,你只能有一个“代码相关”的键(也就是说,TikZ 无法根据参数确定要调用哪个代码)。最简单的方法可能是将join上面代码中引入的新方法更改为,myjoin并在你想要标记的任何地方使用它。所以tikzset会变成:

tikzset{myjoin/.code 2 args=\tikzset{after node path={%
\ifx\tikzchainprevious\pgfutil@empty\else(\tikzchainprevious)%
edge[every join,#1]#2(\tikzchaincurrent)\fi}}}

然后,您可以myjoin={options}{labeling node}在需要标签的地方以及join=with ... by ...需要旧行为的地方使用。选择一个比这更合适的名称可能是明智的myjoin

如果您喜欢这种详细(也许更易读)的使用键的方式,您可以myjoin按如下方式定义选项:

\tikzset{myjoin/.code args={style #1 and label #2}{%
\tikzset{after node path={\ifx\tikzchainprevious\pgfutil@empty%
\else(\tikzchainprevious)edge[every join,#1]#2(\tikzchaincurrent)\fi}}}}

可以用作

\chainin (dec) [myjoin=style tip and label {node [left] {yes}}];

答案2

因此,在分析了wh1t3 的解决方案,以及链库,我试图实现一个允许我使用代码join并添加标签的解决方案。

我不确定这是否是正确的方法,因为我以前从未这样做过,所以如果有更好的方法请告诉我。我重新定义了库的函数以允许label添加关键字,它将添加我缺少的带有标签的节点。要添加的代码是:

\makeatletter
\def\tikz@lib@parse@join#1{%
  \def\tikz@temp{#1}%
  \ifx\tikz@temp\pgfutil@empty%
    \tikz@lib@parse@join@by by \pgf@stop%
  \else%
    \pgfutil@in@{with }{#1}% 
    \ifpgfutil@in@% 'with [by] [label]'
      \pgfutil@in@{by }{#1}%
      \ifpgfutil@in@% 'with by [label]'
        \pgfutil@in@{label }{#1}%
        \ifpgfutil@in@% 'with by label'
          \tikz@lib@parse@join@with@by@label#1\pgf@stop%
        \else% 'with by'
          \tikz@lib@parse@join@with@by#1\pgf@stop%
        \fi%
      \else% 'with [label]'
        \pgfutil@in@{label }{#1}%
        \ifpgfutil@in@% 'with label'
          \tikz@lib@parse@join@with@label#1\pgf@stop%
        \else% with
          \tikz@lib@parse@join@with@by#1 by \pgf@stop%
        \fi%
      \fi%
    \else% '[by] [label]'
      \pgfutil@in@{by }{#1}%
      \ifpgfutil@in@% 'by [label]'
        \pgfutil@in@{label }{#1}%
        \ifpgfutil@in@% 'by label'
          \tikz@lib@parse@join@by@label#1\pgf@stop%
        \else% 'by'
          \tikz@lib@parse@join@by#1\pgf@stop%
        \fi%
      \else% '[label]'
        \pgfutil@in@{label }{#1}%
        \ifpgfutil@in@% 'label'
          \tikz@lib@parse@join@label#1\pgf@stop%
        \else%
          \tikz@lib@parse@join@by#1 by \pgf@stop%
        \fi%
      \fi%
    \fi%
  \fi%
}
\def\tikz@lib@parse@join@with@by@label with #1 by #2 label #3\pgf@stop{%
  \tikzset{after node path={(#1)edge[every join,#2]#3(\tikzchaincurrent)}}%
}
\def\tikz@lib@parse@join@with@label with #1 label #2\pgf@stop{%
  \tikzset{after node path={(#1)edge[every join]#2(\tikzchaincurrent)}}%
}
\def\tikz@lib@parse@join@by@label by #1 label #2\pgf@stop{%
  \tikzset{after node path={\ifx\tikzchainprevious\pgfutil@empty\else(\tikzchainprevious)edge[every join,#1]#2(\tikzchaincurrent)\fi}}%
}
\def\tikz@lib@parse@join@label label #1\pgf@stop{%
  \tikzset{after node path={\ifx\tikzchainprevious\pgfutil@empty\else(\tikzchainprevious)edge[every join]#1(\tikzchaincurrent)\fi}}%
}
\makeatother

添加该部分后,现在我可以调用我的chainin类似功能:

\chainin (node) [join=with anotherNode by myStyle label {node[above] {some Tag}}];
\chainin (node) [join=by myStyle label {node[above] {some Tag}}];

一个完整的例子是

\documentclass{standalone}

\usepackage{tikz}
\usetikzlibrary{shapes,chains,scopes,matrix}

\makeatletter
\def\tikz@lib@parse@join#1{%
  \def\tikz@temp{#1}%
  \ifx\tikz@temp\pgfutil@empty%
    \tikz@lib@parse@join@by by \pgf@stop%
  \else%
    \pgfutil@in@{with }{#1}% 
    \ifpgfutil@in@% 'with [by] [label]'
      \pgfutil@in@{by }{#1}%
      \ifpgfutil@in@% 'with by [label]'
        \pgfutil@in@{label }{#1}%
        \ifpgfutil@in@% 'with by label'
          \tikz@lib@parse@join@with@by@label#1\pgf@stop%
        \else% 'with by'
          \tikz@lib@parse@join@with@by#1\pgf@stop%
        \fi%
      \else% 'with [label]'
        \pgfutil@in@{label }{#1}%
        \ifpgfutil@in@% 'with label'
          \tikz@lib@parse@join@with@label#1\pgf@stop%
        \else% with
          \tikz@lib@parse@join@with@by#1 by \pgf@stop%
        \fi%
      \fi%
    \else% '[by] [label]'
      \pgfutil@in@{by }{#1}%
      \ifpgfutil@in@% 'by [label]'
        \pgfutil@in@{label }{#1}%
        \ifpgfutil@in@% 'by label'
          \tikz@lib@parse@join@by@label#1\pgf@stop%
        \else% 'by'
          \tikz@lib@parse@join@by#1\pgf@stop%
        \fi%
      \else% '[label]'
        \pgfutil@in@{label }{#1}%
        \ifpgfutil@in@% 'label'
          \tikz@lib@parse@join@label#1\pgf@stop%
        \else%
          \tikz@lib@parse@join@by#1 by \pgf@stop%
        \fi%
      \fi%
    \fi%
  \fi%
}
\def\tikz@lib@parse@join@with@by@label with #1 by #2 label #3\pgf@stop{%
  \tikzset{after node path={(#1)edge[every join,#2]#3(\tikzchaincurrent)}}%
}
\def\tikz@lib@parse@join@with@label with #1 label #2\pgf@stop{%
  \tikzset{after node path={(#1)edge[every join]#2(\tikzchaincurrent)}}%
}
\def\tikz@lib@parse@join@by@label by #1 label #2\pgf@stop{%
  \tikzset{after node path={\ifx\tikzchainprevious\pgfutil@empty\else(\tikzchainprevious)edge[every join,#1]#2(\tikzchaincurrent)\fi}}%
}
\def\tikz@lib@parse@join@label label #1\pgf@stop{%
  \tikzset{after node path={\ifx\tikzchainprevious\pgfutil@empty\else(\tikzchainprevious)edge[every join]#1(\tikzchaincurrent)\fi}}%
}
\makeatother

\begin{document}

\begin{tikzpicture}[auto,
  decision/.style = {draw,
                     diamond,
                     text badly centered,
                     fill          = blue!5,
                     text width    = 15mm,
                     node distance = 2.5cm,
                     inner sep     = 0pt},
  block/.style    = {draw,
                     rectangle,
                     text centered,
                     rounded corners,
                     fill           = blue!5,
                     text width     = 20mm,
                     minimum height = 10mm},
  tip/.style      = {->,
                     very thick,
                     color = black!50},
  tip2/.style      = {->,
                     very thick,
                     bend right,
                     color = black!50}
]

\matrix[row sep=1cm]{
\node [block] (blk) {A block here}; \\
\node [decision] (dec) {Is something?};\\
\node [block] (blk2) {Another block};\\
};

{ [start chain]
  \chainin (blk);
  % Removing the 'by tip' style this compiles
  \chainin (dec) [join=by tip label {node [left] {yes}}];
  \chainin (blk2) [join=by tip];
  \chainin (blk2) [join=with blk by {tip2} label {node[left]{my tag}}];
}

\end{tikzpicture}
\end{document}

相关内容