我正在尝试在嵌套的 tikzpictures 中不具有直接父子关系的节点之间绘制一条路径。代码如下所示:
\begin{tikzpicture}
%Container 1
\node [draw] at (0,0) (container1) {
\begin{tikzpicture}
\node at (0,0) (container1label) {Node 1};
\node [draw,below=0.4 of container1label] (child1) {Node 1's Child};
\end{tikzpicture}
};
%Container 2
\node [draw] at (6,0) (container2) {
\begin{tikzpicture}
\node at (0,0) (container2label) {Node 2};
\node [draw,below=0.4 of container2label] (child2) {Node 2's Child};
\end{tikzpicture}
};
%Arrow, it should have been '\path (child1) edge[<->] (child2);' but it's not possible
\draw [<->] (2.17,1.65) to [out=0,in=180](6.1,1.9);
\end{tikzpicture}
这是不可能的,这很有道理,但这意味着我在某个地方做错了,可能是在嵌套 tikzpictures 时出错了。我绝对必须在视觉上将节点放在彼此内部,但如果有其他方法,则不一定需要嵌套 tikzpictures。实现此目的的正确方法是什么?
答案1
这里有三种不同的方式来绘制和连接nested
节点,而无需使用嵌套tikzpictures
。
第一种是使用fit
库绘制一个fitting
节点,覆盖child
和label
节点。合适的节点是container
。由于容器是在其他节点之后绘制的,因此如果要填充它,必须绘制节点on background layer
。
%Container 1
\node at (0,0) (container1label) {Node 1};
\node [draw,below=0.4 of container1label] (child1) {Node 1's Child};
\node[fit=(container1label) (child1),draw] (container1) {};
第二个使用matrix
节点作为container
。
container/.style={matrix, draw, row sep=4mm}
\node[container] (container1) {
\node (container1label) {Node 1}; \\
\node [draw] (child1) {Node 1's Child}; \\
};
background
在这种情况下,如果您想将特殊样式应用于matrix
节点,则无需使用库。
最后一个使用pics
。Apic
允许绘制复杂的图形(不仅仅是节点)并复制它们,而无需使用嵌套tikzpictures
[pics/container/.style 2 args={
code={
\node (-clabel) {#1};
\node[draw, below=0.4 of -clabel] (-cchild) {#2};
},
background code={
\node[fit=(-clabel) (-cchild),draw,pic actions] (-ccont) {};
}}]
它pic
有两个参数,分别是label
和child
文本。我使用了第一个解决方案,两个节点和一个拟合节点,尽管使用解决方案可以获得类似的结果matrix
。
这三种解决方案均提供了下图:
请查看完整的代码以了解如何在pic
解决方案中使用节点标签:
\documentclass[tikz,border=3mm]{standalone}
\usetikzlibrary{fit,positioning,backgrounds}
\begin{document}
\begin{tikzpicture}
%Container 1
\node at (0,0) (container1label) {Node 1};
\node [draw,below=0.4 of container1label] (child1) {Node 1's Child};
\node[fit=(container1label) (child1),draw] (container1) {};
%Container 2
\node at (6,0) (container2label) {Node 2};
\node [draw,below=0.4 of container2label] (child2) {Node 2's Child};
\begin{scope}[on background layer]
\node[fit=(container2label) (child2),draw,fill=red!30] (container2) {};
\end{scope}
\path (child1) edge[<->] (child2);
\end{tikzpicture}
\begin{tikzpicture}[container/.style={matrix, draw, row sep=4mm}]
%Container 1
\node[container] (container1) {
\node (container1label) {Node 1}; \\
\node [draw] (child1) {Node 1's Child}; \\
};
%Container 2
\node[container,fill=red!30] at (6,0) (container2) {
\node (container2label) {Node 2}; \\
\node [draw] (child2) {Node 2's Child}; \\
};
\path (child1) edge[<->] (child2);
\end{tikzpicture}
\begin{tikzpicture}[pics/container/.style 2 args={
code={
\node (-clabel) {#1};
\node[draw, below=0.4 of -clabel] (-cchild) {#2};
},
background code={
\node[fit=(-clabel) (-cchild),draw,pic actions] (-ccont) {};
}}]
\pic (c1) {container={Node 1}{Node 1's Child}};
\pic[fill=red!30] (c2) at (6,0) {container={Node 2}{Node 2's Child}};
\path (c1-cchild) edge[<->] (c2-cchild);
\end{tikzpicture}
\end{document}
答案2
我最终设法通过 fit 库和 PGF 层找到了解决方案:
\usetikzlibrary{fit}
\pgfdeclarelayer{parentlayer}
\pgfdeclarelayer{childlayer}
\pgfdeclarelayer{arrowlayer}
% Can add more layers if needed
\pgfsetlayers{parentlayer,childlayer,arrowlayer}
\begin{tikzpicture}
\begin{pgfonlayer}{childlayer}
\node at (0,0) (container1label) {Node 1};
\node [draw,fill=orange,fill opacity=0.5,text opacity=1,below=0.4 of container1label] (child1) {Node 1's Child};
\node at (4,2) (container2label) {Node 2};
\node [draw,fill=orange,fill opacity=0.5,text opacity=1,below=0.4 of container2label] (child2) {Node 2's Child};
\end{pgfonlayer}
\begin{pgfonlayer}{parentlayer}
\node [draw,fill=cyan,fill opacity=0.3,fit=(container1label) (child1)] (container1) {};
\node [draw,fill=cyan,fill opacity=0.3,fit=(container2label) (child2)] (container2) {};
\end{pgfonlayer}
\begin{pgfonlayer}{arrowlayer}
\draw [<->,color=red] (child1) to [out=0,in=180](child2);
\end{pgfonlayer}
\end{tikzpicture}
在嵌套图表的逻辑嵌套部分方面,它并不漂亮。但它不需要手动摆弄,可以根据需要嵌套任意多层,并保留深度关系,即在父级上绘制子级。
答案3
这是一种嵌套tikzpicture
方法。两个节点被包裹在一个带有选项tikzpicture
的环境中remember picture and overlay
。使用相对距离(通过定位库)来放置节点 1 和节点 2。
代码
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc,positioning,fit}
\begin{document}
\begin{tikzpicture}[remember picture,overlay]
%Container 1
\node (container1) {
\begin{tikzpicture}
\node at (0,0) (container1label) {Node 1};
\node [draw,below=0.4 of container1label] (child1) {Node 1's Child};
\node[draw,fit=(container1label)(child1)](containerA){};
\end{tikzpicture}
};
%Container 2
\node [right= 6cm of container1]
(container2) {
\begin{tikzpicture}
\node at (0,0) (container2label) {Node 2};
\node [draw,below=0.4 of container2label] (child2) {Node 2's Child};
\node[draw,fit=(container2label)(child2)](containerB){};
\end{tikzpicture}
};
%Arrow, it should have been '\path (child1) edge[<->] (child2);' but it's not possible
\draw [<->] (child1) to [out=0,in=180](child2);
\end{tikzpicture}
\end{document}