![TikZ 节点宽度取决于两个节点的距离](https://linux22.com/image/463112/TikZ%20%E8%8A%82%E7%82%B9%E5%AE%BD%E5%BA%A6%E5%8F%96%E5%86%B3%E4%BA%8E%E4%B8%A4%E4%B8%AA%E8%8A%82%E7%82%B9%E7%9A%84%E8%B7%9D%E7%A6%BB.png)
我正在尝试制作一个示意图,其中我需要一个矩形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)
节点,并且below
A
B
和设置minimum width
使得它与和一样宽A
(B
即所述边界框)。
outer xsep
它实际上会减去的两倍,因为这也包括在和minimum width
的测量中。(对于忽略 和 的不同值的形状,这不会很好地起作用,但为圆设置不同的宽度和高度一开始就不会起作用。)A
B
circle
outer xsep
outer 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
。