É possível declarar que os nós nas linhas estão na camada principal independentemente das linhas estarem na camada de fundo? Por exemplo:
Com o seguinte 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}
Eu recebo:
A primeira imagem obtenho desenhando duas segundas linhas: primeiro como linha e sobre ela novamente uma linha invisível com nó. Como meus diagramas reais têm até uma dúzia dessas linhas, procuro soluções mais convenientes para declarar que os nós estão no plano principal, mesmo que a linha esteja em segundo plano.
Responder1
Vamos brincar com caixas.
Em algum momento, TikZ apresenta as chavesbehind path
e in front of path
(para voltar) que basicamente especifica uma ou outra caixa de caminho em que os nós são colocados. Quando o caminho é finalmente desenhado (dentro do ;
final dos caminhos) estas caixas são “usadas”:
- o de fundo (
\tikz@figbox@bg
) - o caminho real é desenhado
- o de primeiro plano (
\tikz@figbox
, que é o padrão para nós)
Quando o TikZ encontra um nó no caminho, na verdade não apenasempatesele desenha o nó em uma dessas duas caixas.
Essas caixas são redefinidas no início do caminho. Essas caixas são a razão pela qual os nós são colocados no topo de seus caminhos (embora, para começar, sejam seus próprios caminhos).
Com oCamadas PGF, algo muito semelhante acontece, mas em vez de apenas um nó, tudo entre \begin{pgfonlayer}
e \end{pgfonlayer}
será colocado dentro dessa caixa.
No final da foto essas caixas ficam “usadas”. (Há algumas tarefas domésticas adicionais que acredito serem para aninhar fotos.)
Agora, em vez de colocar o nó na caixa que é usado pelo TikZ no ;
podemostentarpara colocá-lo diretamente em uma das camadas.
Como isso acontece em algum lugar profundo em alguns grupos, isso precisa ser global (e de fato \pgfonlayer
também é global, já que isso pode ser usado dentro de um escopo em algum lugar - e de fato será quando você usar on background layer
).
Para implementar isso, troco um \setbox
(felizmente o primeiro) por um customizado \tikz@setbox@which
- que é deixado \setbox
funcionar como normalmente funcionaria - dentro daquela macro que coloca o nó naquela caixa para o caminho.
A node on layer
chave apenas faz com que \tikz@setbox@which
seja global \setbox
e que a caixa seja uma das camadas e não uma das caixas de caminho.
Agora você pode dizer
\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}
E isso já mostra o que não funciona com isso:
A
main
camada não pode ser escolhida (é uma camada especial que\pgfonlayer
também não pode ser escolhida).transform canvas
não funcionará (mas também não funciona combehind path
). Pode haver maneiras de contornar isso, mas o manual recomenda:Resumindo, você não deve usar transformações de canvas a menos que realmente saiba o que está fazendo.
e vou adicionar… a menos que você realmente precise.
Substituí sua adição por
LC
uma transformação normal dentro daLC'
chave que é adicionada manualmente a cada coordenada. (Eu gostaria que houvesse alguma maneira de “desfixar” coordenadas/nós para que eles atuassem como coordenadas normais e as transformações se aplicassem a eles também, mas mesmo o manual oferece apenasuma solução alternativa @-ridden.)
Além disso, não o use com outra coisa além de nós. A macro “decisora” \tikz@whichbox
não é usada apenas para nós, mas também para arestas, marcas de plotagem, matrizes, nós filhos (não o mesmo que nós simples) e fotos. Usar \node on layer
lá não vai funcionar, na melhor das hipóteses suas bordas, marcas de plotagem, matriz, filhos e fotos simplesmente não aparecerão. (Porque a adição à caixa é esquecida após o caminho atual de qualquer maneira.) Mais patches precisam ser feitos para isso.
Dito isto, você também pode simplesmente colocar um nó/coordenada vazio ao longo do caminho (para salvar a posição e a rotação) e depois fazer referência a isso colocando o nó real no final de todo o desenho de linha. Porém, isso exigirá uma boa manutenção para torná-lo fácil de usar.
E então há o todoPosicionamento de nó diferidoonde você primeiro “faz” um nó, mas o coloca depois (usado pela forest
biblioteca de desenho gráfico). Isso também não é muito simples. (Mais caixas!)
Código
\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}
Saída
Responder2
Que tal colocar o nó na camada frontal com um comando de caminho de acompanhamento:
\path (b1) to node[X,anchor=east,yshift=-2mm] {ACK(AckNum$=$1000)} (a2);
Aqui está o documento completo:
\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}