我定义了几个命令,每个命令都会输出一堆 TikZ 节点,这些节点组合起来,在概念上代表单个节点/对象。为了将生成的节点视为一个整体,我将它们包装在一个范围内。
\instruction{identifier base}{text L}{text R}{box style}{length style}{scope style}
\twoPInstruction{identifier base}{text L}{textR}{box style}{len1}{len3}{scope style}
通过这些命令,我想创建链式图这些色彩鲜艳的指令块彼此相邻放置。
我得到的只是这张重叠的图画:
但我希望它们相邻对齐:(类似这样)
(我的渲染图周围的灰色轮廓和黑色方框是由 texmaker 的预览造成的)
我曾尝试调整 TikZ 的node distance
样式,但无论我选择多远的距离,我都无法将橙色框与蓝色框分离。
这是我的(超长)MWE。不过,大部分都是样式;有趣的事情发生在\newcommand
s 和末尾附近\begin{tikzpicture}
:
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{arrows,decorations.pathmorphing,positioning,calc,matrix,fit,shapes.miscs,scopes,chains}
\tikzstyle{base}=[
font={\sffamily\bfseries},
]
\tikzstyle{box}=[
base,
rounded rectangle,
draw=black,
inner sep=0.5ex,
]
\tikzstyle{boxL}=[
box,
rounded rectangle right arc=none,
]
\tikzstyle{boxR}=[
box,
rounded rectangle left arc=none,
]
\tikzstyle{inner}=[
base,
inner sep=0,
node distance=0,
line width=0,
]
\tikzstyle{innerL}=[
inner,
font={\small\sffamily\bfseries\color{white}},
]
\tikzstyle{innerR}=[
inner,
font={\small\sffamily\bfseries\color{black}},
]
\tikzstyle{innerLine}=[
->,
dashed,
dash pattern=on 0.25ex off 0.125ex,
decorate,
decoration={
snake,
amplitude=0.18ex,
segment length=1ex,
post length=0.5ex
},
]
\tikzstyle{hop}=[
->,
out=45,
in=135,
dashed,
dash pattern=on 0.25ex off 0.125ex,
]
\tikzstyle{sep}=[
inner,
minimum width=1ex,
]
\tikzstyle{blue}=[
fill=cyan,
]
\tikzstyle{orange}=[
fill=orange,
]
\tikzstyle{len1}=[
inner,
text width=6ex,
]
\tikzstyle{len2}=[
inner,
text width=13ex,
]
\tikzstyle{len3}=[
inner,
text width=19ex,
]
\tikzstyle{len4}=[
inner,
text width=25ex,
]
\pgfdeclarelayer{box}
\pgfdeclarelayer{text}
\pgfsetlayers{box,text,main}
\newcommand{\baseInstruction}[7]{% id-base, text L, text R, color style, box style, length style, scope style
{[#7]
\begin{pgfonlayer}{text}%box contents
\node[#6] (#1 Skel) {};
\node[innerL, right=of #1 Skel.base west, anchor=base west] (#1 SkelL) {#2};
\node[innerR, left=of #1 Skel.base east, anchor=base east] (#1 SkelR) {#3};
\node[inner, fit=(#1 SkelL.north east)(#1 SkelR.south west)] (#1 Between1) {};
\node[inner, fit=(#1 SkelL.south east)(#1 SkelR.north west)] (#1 Between2) {};
\node[inner, fit=(#1 Between1)(#1 Between2)] (#1 Between) {};
\node[inner, fit=(#1 SkelL)(#1 SkelR)] (#1 Contents) {}; %needed for attaching arrows to
\draw[innerLine] ($(#1 Between.west) + (0.2ex,0)$) -- ($(#1 Between.east) - (0.2ex,0)$);
\end{pgfonlayer}
\begin{pgfonlayer}{box}%box outlines
\node[#5, #4, fit=(#1 SkelL)(#1 SkelR)] (#1) {};
\end{pgfonlayer}
}
}
\newcommand{\instruction}[6]{% id-base, text L, text R, color style, length style, scope style
\baseInstruction{#1}{#2}{#3}{#4}{box}{#5}{#6}
}
\newcommand{\instructionL}[6]{% id-base, text L, text R, color style, length style, scope style
\baseInstruction{#1L}{#2}{#3}{#4}{boxL}{#5}{#6}
}
\newcommand{\instructionR}[6]{% id-base, text L, text R, color style, length style, scope style
\baseInstruction{#1R}{#2}{#3}{#4}{boxR}{#5}{#6}
}
\newcommand{\twoPInstruction}[7]{% id-base, text L, text R, color style, length style L, length style R, scope style
{[#7]
\instructionL{#1}{#2}{\vphantom{#3}}{#4}{#5}{}
\begin{pgfonlayer}{text}%box contents
\node[sep, right=of #1L Skel.base east] (#1 Sep) {};
\end{pgfonlayer}
\instructionR{#1}{\vphantom{#2}}{#3}{#4}{#6, right=of #1 Sep}{}
\begin{pgfonlayer}{text}
\draw ($(#1L Between.east) + (0,0.3ex)$) edge[hop] ($(#1R Between.west) + (0,0.3ex)$);
\end{pgfonlayer}
}
}
\begin{document}
\begin{tikzpicture}[
start chain,
node distance=10cm,
every child node/.style={on chain,join},
every join/.style={->}
]
\instruction{a}{a}{X}{blue}{len2}{}
\twoPInstruction{b}{b}{Y}{orange}{len1}{len3}{}
\end{tikzpicture}
\end{document}
答案1
首先,您需要包含scopes
库以使范围简写正常工作。
其次,node distance
仅适用于使用positioning
等键放置的节点,right=of a
您在此处不使用它们来将两个主节点相对于彼此定位。
因此,对代码最快的修复(包括之后scopes
)是手动移动第二个节点:
\begin{tikzpicture}
\instruction{a}{a}{X}{blue}{len2}{}
\twoPInstruction{b}{b}{Y}{orange}{len1}{len3}{xshift=2cm}
\end{tikzpicture}
此外,您可以考虑使用多部分节点,而不是手动绘制形状。
另一种选择是使用嵌套的tikzpicture
,只有两个节点\node (a) {\tikz{...}};
,\node[right=of a] (b) {\tikz{...}};
这样您就可以将两个“逻辑”节点用作“模块”,从而fit
无需使用。
答案2
根据建议@Bordaigorl的回答和评论\instruction
,我已经将和的主体包裹\twoPInstruction
在节点和 tikzpictures 中。
\newcommand{\baseInstruction}[7]{% id-base, text L, text R, color style, box style, length style, scope style
{
\begin{pgfonlayer}{text}%box contents
\node[#6] (#1 Skel) {};
\node[innerL, right=of #1 Skel.base west, anchor=base west] (#1 SkelL) {#2};
\node[innerR, left=of #1 Skel.base east, anchor=base east] (#1 SkelR) {#3};
\node[inner, fit=(#1 SkelL.north east)(#1 SkelR.south west)] (#1 Between1) {};
\node[inner, fit=(#1 SkelL.south east)(#1 SkelR.north west)] (#1 Between2) {};
\node[inner, fit=(#1 Between1)(#1 Between2)] (#1 Between) {};
\node[inner, fit=(#1 SkelL)(#1 SkelR)] (#1 Contents) {}; %needed for attaching arrows to
\draw[innerLine] ($(#1 Between.west) + (0.2ex,0)$) -- ($(#1 Between.east) - (0.2ex,0)$);
\end{pgfonlayer}
\begin{pgfonlayer}{box}%box outlines
\node[#5, #4, fit=(#1 SkelL)(#1 SkelR)] (#1 Box) {};
\end{pgfonlayer}
}}
\newcommand{\instruction}[6]{% id-base, text L, text R, color style, length style, scope style
\node [#6] (#1) {\tikz{
\baseInstruction{#1}{#2}{#3}{#4}{box}{#5}{}
}};
}
\newcommand{\instructionL}[6]{% id-base, text L, text R, color style, length style, scope style
\baseInstruction{#1L}{#2}{#3}{#4}{boxL}{#5}{#6}
}
\newcommand{\instructionR}[6]{% id-base, text L, text R, color style, length style, scope style
\baseInstruction{#1R}{#2}{#3}{#4}{boxR}{#5}{#6}
}
\newcommand{\twoPInstruction}[7]{% id-base, text L, text R, color style, length style L, length style R, scope style
\node [#7] (#1) {\tikz{
\instructionL{#1}{#2}{\vphantom{#3}}{#4}{#5}{}
\begin{pgfonlayer}{text}%box contents
\node[sep, right=of #1L Skel.base east] (#1 Sep) {};
\end{pgfonlayer}
\instructionR{#1}{\vphantom{#2}}{#3}{#4}{#6, right=of #1 Sep}{}
\begin{pgfonlayer}{text}
\draw[hop] ($(#1L Between.east) + (0,0.3ex)$) to[hop] ($(#1R Between.west) + (0,0.3ex)$);
\end{pgfonlayer}
}};
}
\begin{tikzpicture}[start chain, node distance=5ex, every join/.style={->},]
\twoPInstruction{b}{b}{Y}{orange}{len1}{len3}{on chain, join}
\instruction{a}{a}{X}{blue}{len2}{on chain, join}
\end{tikzpicture}
但是反转a
并b
最初在行上给了我一个错误\twoPInstruction
:“!包 pgf 错误:没有已知的名为 chain-2 的形状。” ...“l.139 ...b}{Y}{orange}{len1}{len3}{on chain, join}”
为了解决这个问题,我不得不摆脱 in edge
,twoPInstruction
因为这会干扰链库。相反,我现在使用to[hop]
。NB,我在一行中使用了hop
两次样式(因为我很懒);一半的样式键应用于\draw
行的一部分,而另一半应用于\to
部分。
\begin{tikzpicture}[start chain, node distance=5ex, every join/.style={->},]
\instruction{a}{a}{X}{blue}{len2}{on chain, join}
\twoPInstruction{b}{b}{Y}{orange}{len1}{len3}{on chain, join}
\end{tikzpicture}
PS:我还从中删除了组样式([#7]
),以\baseInstruction
避免日志中出现警告。