TikZ 节点宽度取决于两个节点的距离

TikZ 节点宽度取决于两个节点的距离

我正在尝试制作一个示意图,其中我需要一个矩形minimum width设置为两个其他矩形节点之间的距离。我尝试遵循以下解决方案计算两个节点之间的 x 距离发布,但在这种情况下我总是会遇到以下错误

\iterate 定义中的参数数量非法。\end{frame}

我猜我忘记了一些东西,但又想不起来是什么。

以下是我想做的事情:

示意图

我的问题是获取绿色和红色矩形的宽度。以下是我目前得到的结果:

\documentclass[aspectratio=169, 14pt, notes]{beamer}

\usepackage{tikz}
\usetikzlibrary{arrows.meta, calc, fit, graphs, math, positioning, shapes, shadows, tikzmark}

\begin{frame}[t]
  \frametitle{My frame}
  \framesubtitle{Example}

  \newcommand\setxveclength[5]{% newmacro, node1, anchor1, node2, anchor2
    \pgfpointdiff{\pgfpointanchor{#2}{#3}}{\pgfpointanchor{#4}{#5}}
    \edef#1{\the\pgf@x}
  }

  \begin{tikzpicture}[remember picture, overlay]
    \node[inner sep=0pt, minimum width=0.30cm, minimum height=2.50cm, rounded corners=0.10cm, draw=gray4, fill=gray5, text=white, font=\tiny]              (PartA)      at ({$(current page.west)!0.25!(current page.east)$} |- {$(current page.north)!0.50!(current page.south)$}) {\rotatebox{270}{AAA}};
    \node[inner sep=0pt, minimum width=0.30cm, minimum height=2.50cm, rounded corners=0.10cm, draw=gray4, fill=gray5, text=white, font=\tiny, anchor=west] (PartB)      at ([xshift=0.50mm]PartA.east) {\rotatebox{270}{BBB}};
    \node[inner sep=0pt, minimum width=0.30cm, minimum height=2.50cm, rounded corners=0.10cm, draw=gray4, fill=gray5, text=white, font=\tiny, anchor=west] (PartC)      at ([xshift=0.50mm]PartB.east) {\rotatebox{270}{CCC}};
    \node[inner sep=0pt, minimum width=0.30cm, minimum height=1.66cm, rounded corners=0.10cm, draw=gray4, fill=gray5, text=white, font=\tiny, anchor=south west] (PartD)at ([xshift=0.50mm]PartC.south east) {\rotatebox{270}{DDD}};
    \node[inner sep=0pt, minimum width=0.30cm, minimum height=1.66cm, rounded corners=0.10cm, draw=gray4, fill=gray5, text=white, font=\tiny, anchor=west] (PartE)      at ([xshift=0.50mm]PartD.east) {\rotatebox{270}{EEE}};
    \node[inner sep=0pt, minimum width=0.30cm, minimum height=1.66cm, rounded corners=0.10cm, draw=gray4, fill=gray5, text=white, font=\tiny, anchor=west] (PartF)      at ([xshift=0.50mm]PartE.east) {\rotatebox{270}{FFF}};
    \node[inner sep=0pt, minimum width=0.30cm, minimum height=2.50cm, rounded corners=0.10cm, draw=gray4, fill=gray5, text=white, font=\tiny, anchor=south west] (PartG)at ([xshift=0.50mm]PartF.south east) {\rotatebox{270}{GGG}};
    \node[inner sep=0pt, minimum width=0.30cm, minimum height=2.50cm, rounded corners=0.10cm, draw=gray4, fill=gray5, text=white, font=\tiny, anchor=west] (PartH)      at ([xshift=0.50mm]PartG.east) {\rotatebox{270}{HHH}};
    \node[inner sep=0pt, minimum width=0.30cm, minimum height=2.50cm, rounded corners=0.10cm, draw=gray4, fill=gray5, text=white, font=\tiny, anchor=west] (PartI)      at ([xshift=0.50mm]PartH.east) {\rotatebox{270}{III}};

    \setxveclength{\mydist}{LinuxComp_Tel}{west}{ActiaSoft_GNSS}{east}
    \node[inner sep=0pt, minimum width=\pgfpointdiff{\pgfpointanchor{PartD}{west}}{\pgfpointanchor{PartF}{east}}, minimum height=0.30cm, rounded corners=0.10cm, draw=gray4, fill=GreenActia, text=white, font=\tiny, anchor=south west]  (PartJ)    at ([yshift=0.50mm]PartD.north west) {JJJ};
  \end{tikzpicture}
\end{frame}

我注意到,问题出现在我声明 \newcommand 后。我不需要调用它

我发现该解决方案通过以下方式创建节点:

\path let \p1=($(PartD.west)-(PartF.east)$), \n1 = {veclen(\p1)}
  in node[inner sep=0pt, minimum width=\n1, minimum height=0.30cm, rounded corners=0.10cm, draw=gray4, fill=green4, text=white, font=\tiny, anchor=south west, name=PartJJJ]  at ([yshift=0.50mm]PartD.north west) {JJJ};

但在这种情况下,我不能重复使用第二个节点的距离,这意味着我必须每次重新计算宽度,并确保用于计算的节点对于具有此特定宽度的每个矩形都是准确的。

谢谢您的帮助,

答案1

ext.positioning-plus这是我制作我的图书馆的例子之一tikz-ext包裹为了。

它将库中的键positioning与库的语法和测量相结合fit,同时进行实际设置minimum width,而不是实际设置text width,如果您实际上想在该节点内排版文本而不必使用标签,这将很有帮助。但这也意味着,如果您在其中放入的文本多于其容纳的文本,节点就会增大。

有了它,你可以说哪个将放置边界框的below = of -(A)(B)节点,并且belowAB 设置minimum width使得它与和一样宽AB即所述边界框)。

outer xsep它实际上会减去的两倍,因为这也包括在和minimum width的测量中。(对于忽略 和 的不同值的形状,这不会很好地起作用,但为圆设置不同的宽度和高度一开始就不会起作用。)ABcircleouter xsepouter ysep


ext.positioning-plus库还定义了一个定位键south right,即

\node[south right=of CCC] (DDD) {DDD};

其工作原理类似于,right = of CCC但使用south east参考上的锚点CCC和节点anchor = south west上的DDD–即,将底部对齐的节点放置在右侧–但由于我选择在此处旋转节点(而不是\rotatebox),所以我将使用自定义west right键。

代码

\documentclass[aspectratio=169, 14pt]{beamer}
\usepackage{tikz, ninecolors}
\usetikzlibrary{ext.positioning-plus, chains}
\tikzset{west right/.style={right=#1.south west, anchor=north west}}
\begin{document}
\begin{frame}[t]
\frametitle{My frame}
\framesubtitle{Example}
\centering % maybe
\begin{tikzpicture}[
  start chain=going west right,
  node distance=.5mm,
  my node/.style={
    inner sep=+0pt, minimum height=+.3cm, rounded corners=+.1cm,
    draw=gray4, fill=gray5, text=white, font=\tiny},
  every on chain/.append style={my node, rotate=90},
  greenish/.style={draw=green4, fill=green5},
  redish/.style={draw=red4, fill=red5}]
\foreach \WIDTH/\NODES in {2.5cm /{AAA, BBB, CCC},
                           1.66cm/{DDD, EEE, FFF},
                           2.5cm /{GGG, HHH, III}}
  \foreach \NODE in \NODES
    \node[on chain, minimum width=\WIDTH]{\NODE};
\node[below=of -(chain-begin)(chain-end), my node, greenish] {MMM};
\node[above=of -(chain-begin)(chain-end), my node, greenish] {LLL};

\node[above=of -(chain-4)(chain-6), my node, redish] (JJJ) {JJJ};
\node[above=of -(JJJ), ultra thick, my node, redish]       {KKK};
\end{tikzpicture}
\end{frame}
\end{document}

输出

在此处输入图片描述

答案2

您可以使用fit节点。该fit选项仅固定节点尺寸,但您可以将其放置在您需要的任何位置。无需涉及参考坐标或节点。

\documentclass[aspectratio=169, 14pt, notes]{beamer}

\usepackage{tikz}
\usepackage{ninecolors}
\usetikzlibrary{arrows.meta, calc, fit, graphs, math, positioning, shapes, shadows, tikzmark}

\begin{document}
\begin{frame}[t]
  \frametitle{My frame}
  \framesubtitle{Example}

%  \newcommand\setxveclength[5]{% newmacro, node1, anchor1, node2, anchor2
%    \pgfpointdiff{\pgfpointanchor{#2}{#3}}{\pgfpointanchor{#4}{#5}}
%    \edef#1{\the\pgf@x}
%  }

  \begin{tikzpicture}[remember picture, overlay]
    \node[inner sep=0pt, minimum width=0.30cm, minimum height=2.50cm, rounded corners=0.10cm, draw=gray4, fill=gray5, text=white, font=\tiny]              (PartA)      at ({$(current page.west)!0.25!(current page.east)$} |- {$(current page.north)!0.50!(current page.south)$}) {\rotatebox{270}{AAA}};
    \node[inner sep=0pt, minimum width=0.30cm, minimum height=2.50cm, rounded corners=0.10cm, draw=gray4, fill=gray5, text=white, font=\tiny, anchor=west] (PartB)      at ([xshift=0.50mm]PartA.east) {\rotatebox{270}{BBB}};
    \node[inner sep=0pt, minimum width=0.30cm, minimum height=2.50cm, rounded corners=0.10cm, draw=gray4, fill=gray5, text=white, font=\tiny, anchor=west] (PartC)      at ([xshift=0.50mm]PartB.east) {\rotatebox{270}{CCC}};
    \node[inner sep=0pt, minimum width=0.30cm, minimum height=1.66cm, rounded corners=0.10cm, draw=gray4, fill=gray5, text=white, font=\tiny, anchor=south west] (PartD)at ([xshift=0.50mm]PartC.south east) {\rotatebox{270}{DDD}};
    \node[inner sep=0pt, minimum width=0.30cm, minimum height=1.66cm, rounded corners=0.10cm, draw=gray4, fill=gray5, text=white, font=\tiny, anchor=west] (PartE)      at ([xshift=0.50mm]PartD.east) {\rotatebox{270}{EEE}};
    \node[inner sep=0pt, minimum width=0.30cm, minimum height=1.66cm, rounded corners=0.10cm, draw=gray4, fill=gray5, text=white, font=\tiny, anchor=west] (PartF)      at ([xshift=0.50mm]PartE.east) {\rotatebox{270}{FFF}};
    \node[inner sep=0pt, minimum width=0.30cm, minimum height=2.50cm, rounded corners=0.10cm, draw=gray4, fill=gray5, text=white, font=\tiny, anchor=south west] (PartG)at ([xshift=0.50mm]PartF.south east) {\rotatebox{270}{GGG}};
    \node[inner sep=0pt, minimum width=0.30cm, minimum height=2.50cm, rounded corners=0.10cm, draw=gray4, fill=gray5, text=white, font=\tiny, anchor=west] (PartH)      at ([xshift=0.50mm]PartG.east) {\rotatebox{270}{HHH}};
    \node[inner sep=0pt, minimum width=0.30cm, minimum height=2.50cm, rounded corners=0.10cm, draw=gray4, fill=gray5, text=white, font=\tiny, anchor=west] (PartI)      at ([xshift=0.50mm]PartH.east) {\rotatebox{270}{III}};

    \node[fit={(PartD.west) (PartF.east)}, inner sep=0pt, minimum height=.3cm, rounded corners=.1cm, draw=gray4,fill=red!70!black, text=white, font=\tiny, anchor=south west, label={[font=\tiny,text=white]center:JJJ}] (PartJ) at ([yshift=0.5mm]PartD.north west){};

    \node[fit={(PartD.west) (PartF.east)}, inner sep=0pt, minimum height=.3cm, rounded corners=.1cm, draw=gray4,fill=red!70!black, text=white, font=\tiny, anchor=south west, label={[font=\tiny,text=white]center:KKK}] (PartK) at ([yshift=0.5mm]PartJ.north west){};

    \node[fit={(PartA.west) (PartI.east)}, inner sep=0pt, minimum height=.3cm, rounded corners=.1cm, draw=gray4,fill=green!70!black, anchor=south west, label={[font=\tiny,text=white]center:LLL}] (PartL) at ([yshift=0.5mm]PartA.north west){};

    \node[fit={(PartA.west) (PartI.east)}, inner sep=0pt, minimum height=.3cm, rounded corners=.1cm, draw=gray4,fill=green!70!black, anchor=north west, label={[font=\tiny,text=white]center:MMM}] (PartM) at ([yshift=-0.5mm]PartA.south west){};
    
%    \setxveclength{\mydist}{LinuxComp_Tel}{west}{ActiaSoft_GNSS}{east}
%    \node[inner sep=0pt, minimum width=\pgfpointdiff{\pgfpointanchor{PartD}{west}}{\pgfpointanchor{PartF}{east}}, minimum height=0.30cm, rounded corners=0.10cm, draw=gray4, fill=GreenActia, text=white, font=\tiny, anchor=south west]  (PartJ)    at ([yshift=0.50mm]PartD.north west) {JJJ};
  \end{tikzpicture}
\end{frame}
\end{document}

在此处输入图片描述

答案3

您可以应用提供的解决方案这个很好的答案。您还可以使用循环和样式来简化您的代码:

\documentclass[border=10pt]{standalone}
\usepackage{ninecolors}
\usepackage{tikz}
\usetikzlibrary{calc}

\begin{document}

    \makeatletter
    \tikzset{
        span nodes horizontally/.style 2 args={
            insert path={
                \pgfextra{
                    \pgfpointdiff{\pgfpointanchor{#1}{west}}{\pgfpointanchor{#2}{east}}
                    \pgf@xa=\pgf@x
                }
            },
            minimum width={\pgf@xa-\pgfkeysvalueof{/pgf/outer xsep}}
        },
        span nodes vertically/.style 2 args={
            insert path={
                \pgfextra{
                    \pgfpointdiff{\pgfpointanchor{#2}{south}}{\pgfpointanchor{#1}{north}}
                    \pgf@ya=\pgf@y
                }
            },
            minimum height={\pgf@ya-\pgfkeysvalueof{/pgf/outer ysep}}
        },
    }
    \makeatother

    \tikzset{
        rounded/.style={
            inner sep=0pt, 
            minimum width=0.30cm, 
            minimum height=0.30cm, 
            rounded corners=0.10cm, 
            draw=gray4,
            fill=gray5, 
            text=white, 
            font=\tiny, 
        }
    }
    \makeatother

    \begin{tikzpicture}
        \coordinate (Init) at ([xshift=-0.50mm]{$(current page.west)!0.25!(current page.east)$} |- {$(current page.north)!0.50!(current page.south)$});
        \foreach \h/\n/\c [remember=\n as \lastn (initially Init)] in {
            2.5/PartA/AAA,
            2.5/PartB/BBB,
            2.5/PartC/CCC,
            1.66/PartD/DDD,
            1.66/PartE/EEE,
            1.66/PartF/FFF,
            2.5/PartG/GGG,
            2.5/PartH/HHH,
            2.5/PartI/III
        } {
            \node[rounded, minimum height={\h*1cm}, anchor=south west] (\n) 
                at ([xshift=0.50mm]\lastn.south east) {\rotatebox{270}{\c}};
        }
    
        \node[rounded, span nodes horizontally={PartD}{PartF}, fill=green4, anchor=south west] (PartJJJ) 
            at ([yshift=0.50mm]PartD.north west) {JJJ};
            
        % variation for vertical span

        \node[rounded, minimum width=2em, anchor=north west] (PartK) 
            at ([yshift=-0.50mm]PartA.south west) {KKK};

        \node[rounded, minimum width=2em, anchor=north west] (PartL) 
            at ([yshift=-0.50mm]PartK.south west) {LLL};

        \node[rounded, span nodes vertically={PartK}{PartL}, fill=green4, anchor=south west] (PartM) 
            at ([xshift=0.50mm]PartL.south east) {\rotatebox{270}{MM}};
            
    \end{tikzpicture}
    
\end{document}

在此处输入图片描述


可能更好、更强大的解决方案是(再次感谢 Qrrbrbirlbel):

\documentclass[border=10pt]{standalone}
\usepackage{ninecolors}
\usepackage{tikz}
\usetikzlibrary{calc}

\begin{document}

    \makeatletter
    \tikzset{
        span nodes horizontally/.code 2 args={
            \pgf@process{\pgfpointdiff{\pgfpointanchor{#1}{west}}{\pgfpointanchor{#2}{east}}}
            \pgfkeyssetevalue{/pgf/minimum width}{\the\pgf@x-2*(\noexpand\pgfkeysvalueof{/pgf/outer xsep})}
        },
        span nodes vertically/.code 2 args={
            \pgf@process{\pgfpointdiff{\pgfpointanchor{#2}{south}}{\pgfpointanchor{#1}{north}}}
            \pgfkeyssetevalue{/pgf/minimum height}{\the\pgf@y-2*(\noexpand\pgfkeysvalueof{/pgf/outer ysep})}
        },
    }
    \makeatother

    \tikzset{
        rounded/.style={
            inner sep=0pt, 
            minimum width=0.30cm, 
            minimum height=0.30cm, 
            rounded corners=0.10cm, 
            draw=gray4,
            fill=gray5, 
            text=white, 
            font=\tiny, 
        }
    }
    \makeatother

    \begin{tikzpicture}
        \coordinate (Init) at ([xshift=-0.50mm]{$(current page.west)!0.25!(current page.east)$} |- {$(current page.north)!0.50!(current page.south)$});
        \foreach \h/\n/\c [remember=\n as \lastn (initially Init)] in {
            2.5/PartA/AAA,
            2.5/PartB/BBB,
            2.5/PartC/CCC,
            1.66/PartD/DDD,
            1.66/PartE/EEE,
            1.66/PartF/FFF,
            2.5/PartG/GGG,
            2.5/PartH/HHH,
            2.5/PartI/III
        } {
            \node[rounded, minimum height={\h*1cm}, anchor=south west] (\n) 
                at ([xshift=0.50mm]\lastn.south east) {\rotatebox{270}{\c}};
        }
    
        \node[rounded, span nodes horizontally={PartD}{PartF}, fill=green4, anchor=south west] (PartJJJ) 
            at ([yshift=0.50mm]PartD.north west) {JJJ};
            
        % variation for vertical span

        \node[rounded, minimum width=2em, anchor=north west] (PartK) 
            at ([yshift=-0.50mm]PartA.south west) {KKK};

        \node[rounded, minimum width=2em, anchor=north west] (PartL) 
            at ([yshift=-0.50mm]PartK.south west) {LLL};

        \node[rounded, span nodes vertically={PartK}{PartL}, fill=green4, anchor=south west] (PartM) 
            at ([xshift=0.50mm]PartL.south east) {\rotatebox{270}{MM}};
            
    \end{tikzpicture}
    
\end{document}

这两种解决方案也可在上下文中起作用beamer

相关内容