如何在嵌套的 tikzpictures 节点之间绘制路径?

如何在嵌套的 tikzpictures 节点之间绘制路径?

我正在尝试在嵌套的 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节点,覆盖childlabel节点。合适的节点是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有两个参数,分别是labelchild文本。我使用了第一个解决方案,两个节点和一个拟合节点,尽管使用解决方案可以获得类似的结果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}

相关内容