如何在与线不同的层上设置线上的节点?

如何在与线不同的层上设置线上的节点?

是否可以声明,无论线条是否在背景层,线条上的节点都在主层上?例如: 在此处输入图片描述

具有以下 MWE:

\documentclass[12pt,tikz,border=3mm]{standalone}
    \usetikzlibrary{arrows,arrows.meta,%
        backgrounds,positioning}
\pgfdeclarelayer{foreground} 
\pgfdeclarelayer{background}
   \pgfsetlayers{background,main,foreground}

    \usepackage{amsmath}
\begin{document}
    \begin{tikzpicture}[
    node distance = 0mm,
        LC/.style = {draw=#1,
            line width=1mm,
            arrows={-Stealth[fill=#1,inset=0pt,length=0pt 1.6,angle'=90]},
            },
         X/.style = {draw, very thin, fill=white, fill opacity=0.75,
            font=\scriptsize,
            text=black, text opacity=1, align=left,
            inner sep=2pt, sloped, anchor=west,pos=0.07},
                        ]\sffamily
%---
\linespread{0.8}
%-------
\coordinate                     (a0)    at (0,0);
\coordinate[right=77mm of a0]   (b0);
    \foreach \i [count=\xi from 0] in {1,2,...,4}
{
    \coordinate[below=7mm of a\xi]  (a\i);
    \coordinate[below=7mm of b\xi]  (b\i);
}
\draw[|->]  (a0) -- (a3) node[above left]   {$t$};
\draw[|->]  (b0) -- (b3) node[above right]  {$t$};
\draw[LC=gray]  (a1)
    to node[X] {data\\
                $(\text{SeqNum}=0,\ell=1000)$}
                (b2);
%-------
    \begin{scope}[ X/.append style={anchor=east},
                  LC/.append style={transform canvas={yshift=-2mm}},
                  on background layer]
\draw[LC=teal]  (b1)
    to node[X] {ACK(AckNum$=$1000)}
                (a2);
   \end{scope}
%----------------
    \end{tikzpicture}
        \end{document}

我得到:

在此处输入图片描述

我通过两次绘制第二条线来获得第一幅图:第一条线是线,第二条是看不见的线,上面有节点。由于我的实际图表有多达十几条这样的线,所以我在寻找更方便的解决方案来声明,即使线在背景中,节点也在主平面中。

答案1

我们来玩盒子吧。

在某个时候,TikZ 引入了键behind pathin front of path(切换回来)基本上指定放置节点的一个或另一个路径框。当最终绘制路径时(在;路径末尾内),这些框会被“使用”:

  1. 背景图 ( \tikz@figbox@bg)
  2. 实际路径被绘制
  3. 前台 ( \tikz@figbox,这是节点的默认设置)

当 TikZ 在路径上找到一个节点时,它实际上并不只是绘制它,它在这两个框中的一个上绘制节点。

这些框在路径的开始处被重置。这些框是节点被放置在其路径顶部的原因(尽管它们一开始就是它们自己的路径)。


随着PGF 层,会发生一些非常类似的事情,但不只是一个节点,\begin{pgfonlayer}和之间的所有内容\end{pgfonlayer}都将放置在该框内。

在图片的最后,这些盒子被“使用”。(还有一些额外的整理工作,我认为是为了嵌套图片。)

;现在,我们不再需要将节点放在 TikZ 使用的框中,而是尝试将其直接放置在其中一个图层上。

由于这发生在几个组的深处,所以这需要是全局的(并且事实上\pgfonlayer它也是全局的,因为它可以在某个范围内使用 - 而且当你使用时它确实会这样on background layer)。


为了实现这一点,我将一个\setbox(幸运的是第一个)换成一个自定义的\tikz@setbox@which- 让它\setbox像往常一样工作 - 在将节点放置在路径的那个框上的宏里面。

关键node on layer是让它成为\tikz@setbox@which一个全局变量\setbox,并且该框是其中一个层而不是路径框之一。

现在你可以说

\begin{scope}[
  X/.append style={anchor=east},
  LC'/.style={yshift=-2mm}, % no transform canvas
  on background layer]
\draw[LC=teal] ([LC'] b1) % ........ ←
  to node[X, node on layer=foreground] {ACK(AckNum$=$1000)} ([LC'] a2);
\end{scope}

这已经显示了什么不起作用:

  • 无法选择该main图层(它是一个特殊的图层,无法用\pgfonlayer任何方式选择)。

  • transform canvas不起作用(但也不适用于behind path)。可能有解决方法,但手册建议:

    简而言之,除非您真正知道自己在做什么,否则不应该使用画布转换。

    我要补充一下…除非你真的需要它

    LC我已经用键内的正常变换替换了您的添加,LC'该变换手动添加到每个坐标。(我确实希望有某种方法可以“取消固定”坐标/节点,以便它们充当正常坐标,并且变换也适用于它们,但即使是手册也只提供一个 @-ridden 的解决方法

此外,不要将它与节点以外的其他东西一起使用。 “decider” 宏\tikz@whichbox不仅用于节点,还用于边、绘图标记、矩阵、子节点(与普通节点不同)和图片。\node on layer在那里使用不会起作用,最多您的边、绘图标记、矩阵、子节点和图片不会显示。 (因为无论如何在当前路径之后都会忘记添加到框中。)必须为此进行更多修补。


也就是说,您也可以沿路径放置一个空节点/坐标(以保存位置和旋转),然后在所有线条绘制的末尾放置实际节点时引用该节点。不过,这需要一些很好的管理才能使其易于使用。

然后还有整个延迟节点定位首先“创建”一个节点,然后放置它(由forest图形绘制库使用)。不过,这也不是很直接。(更多框!)

代码

\documentclass[12pt, tikz, border=3mm]{standalone}
\usetikzlibrary{arrows, arrows.meta, backgrounds, positioning}
\pgfdeclarelayer{foreground}\pgfdeclarelayer{background}
\pgfsetlayers{background,main,foreground}
\makeatletter\ExplSyntaxOn % replace only first one
\tl_replace_once:Nnn \tikz@fig@continue { \setbox } { \tikz@setbox@which }
\ExplSyntaxOff
\let\tikz@setbox@which\setbox
\tikzset{node on layer/.code={%
  \expandafter\def\expandafter\tikz@whichbox\expandafter
    {\csname pgf@layerbox@#1\endcsname}%
  \def\tikz@setbox@which{\global\setbox}}}
\makeatother
\usepackage{amsmath}
\begin{document}
\begin{tikzpicture}[
  node distance = 0mm,
  LC/.style = {draw=#1, line width=1mm,
    arrows={-Stealth[fill=#1,inset=0pt,length=0pt 1.6,angle'=90]}},
  X/.style = {draw, very thin, fill=white, fill opacity=0.75,
    font=\scriptsize, text=black, text opacity=1, align=left,
   inner sep=2pt, sloped, anchor=west,pos=0.07}]
\sffamily\linespread{0.8}

\coordinate                     (a0)    at (0,0);
\coordinate[right=77mm of a0]   (b0);
\foreach \i [count=\xi from 0] in {1,2,...,4}
  \coordinate[below=7mm of a\xi]  (a\i)
   coordinate[below=7mm of b\xi]  (b\i);
\draw[|->] (a0) -- (a3) node[above left]   {$t$};
\draw[|->] (b0) -- (b3) node[above right]  {$t$};
\draw[LC=gray] (a1) to node[X] {data\\$(\text{SeqNum}=0,\ell=1000)$} (b2);

\begin{scope}[
  X/.append style={anchor=east},
  LC'/.style={yshift=-2mm}, % no transform canvas
  on background layer]
\draw[LC=teal] ([LC'] b1)
  to node[X, node on layer=foreground] {ACK(AckNum$=$1000)} ([LC'] a2);
\end{scope}
\end{tikzpicture}
\end{document}

输出

在此处输入图片描述

答案2

如何使用后续路径命令将节点放置在前层:

\path (b1) to node[X,anchor=east,yshift=-2mm] {ACK(AckNum$=$1000)} (a2);

以下是完整文档:

\documentclass[12pt,tikz,border=3mm]{standalone}
\usetikzlibrary{arrows,arrows.meta,backgrounds,positioning}
\pgfdeclarelayer{foreground} 
\pgfdeclarelayer{background}
\pgfsetlayers{background,main,foreground}
\usepackage{amsmath}

\begin{document}

\begin{tikzpicture}
  [
    node distance = 0mm,
    LC/.style = {draw=#1,
                 line width=1mm,
                 arrows={-Stealth[fill=#1,inset=0pt,length=0pt 1.6,angle'=90]},
                },
    X/.style = {draw, 
                very thin, 
                fill=white, 
                fill opacity=0.75,
                font=\scriptsize,
                text=black, 
                text opacity=1, 
                align=left,
                inner sep=2pt, 
                sloped, 
                anchor=west,
                pos=0.07},
  ]
 \sffamily
%---
  \linespread{0.8}
%-------
  \coordinate                     (a0)    at (0,0);
  \coordinate[right=77mm of a0]   (b0);
  \foreach \i [count=\xi from 0] in {1,2,...,4}
    {
      \coordinate[below=7mm of a\xi]  (a\i);
      \coordinate[below=7mm of b\xi]  (b\i);
    } 
  \draw[|->]  (a0) -- (a3) node[above left]   {$t$};
  \draw[|->]  (b0) -- (b3) node[above right]  {$t$};
  \draw[LC=gray]  (a1)
                  to 
                  node[X] {data\\
                  $(\text{SeqNum}=0,\ell=1000)$}
                  (b2);
%-------
  \begin{scope}[X/.append style={anchor=east},
                LC/.append style={transform canvas={yshift=-2mm}},
                on background layer]
    \draw[LC=teal]  (b1)
                    to 
                    (a2);
 \end{scope}
%----------------
  \path (b1) to node[X,anchor=east,yshift=-2mm] {ACK(AckNum$=$1000)} (a2);
\end{tikzpicture}
\end{document}

在此处输入图片描述

相关内容