是否可以聲明,無論線條在背景層中,線條上的節點都在主層上?例如:
具有以下 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 path
和in front of path
(切換回來)它基本上指定了節點所在的一個或另一個路徑框。當路徑最終被繪製時(在;
路徑末尾),這些框被「使用」:
- 背景一 (
\tikz@figbox@bg
) - 繪製實際路徑
- 前台節點(
\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}