如何將線上的節點設定在與線不同的圖層上?

如何將線上的節點設定在與線不同的圖層上?

是否可以聲明,無論線條在背景層中,線條上的節點都在主層上?例如: 在此輸入影像描述

具有以下 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}

在此輸入影像描述

相關內容