以下代码创建了两种样式\pic
。目标是将\pic
s 定位为垂直相对的椭圆相距 1em,水平相邻的椭圆相距 1em。(后者当然仅适用于水平方向最接近的椭圆的行 - 另一行中的椭圆由于垂直对齐而可能相距更远)。
使用和\pic
来相对定位s会出错。绝对定位似乎也行不通,因为椭圆的宽度是未知的(想象一下代码与椭圆中的其他文本值重复使用)。right=of
below=of
如何才能\pic
正确定位 s 呢?
\documentclass[tikz]{standalone}
\usetikzlibrary{positioning,calc,fit,shapes}
\tikzset {
factor/.style = {draw, ellipse},
indicator/.style = {draw, rectangle, outer sep=0},
arr/.style={-latex},
pics/collDown/.style n args={2}{
code={%
\node[indicator] ({#1}1) {{#1}};
\node[factor, above=2em of {#1}1] (#1) {#2};
\draw[arr] (#1) -- ({#1}1.north);
}
},
pics/collUp/.style n args={2}{
code={%
\node[indicator] ({#1}1) {{#1}};
\node[factor, below=2em of {#1}1] (#1) {#2};
\draw[arr] (#1) -- ({#1}1.south);
}
}
}
\begin{document}
\begin{tikzpicture}
\pic[local bounding box=a] {collUp={A}{Some text}};
\pic[local bounding box=b, right=1em of a] {collUp={B}{More text}};
\pic[local bounding box=c, below=1em of a] {collDown={C}{Weird stuff}};
\pic[local bounding box=d, below=1em of b] {collDown={D}{I'm giving up}};
\pic at (0,-5) {collUp={A}{Some text}};
\pic at (3,-5) {collUp={B}{More text}};
\pic at (0,-9) {collDown={C}{Weird stuff}};
\pic at (3,-9) {collDown={D}{I'm giving up}};
\end{tikzpicture}
\end{document}
答案1
这是一个非常好的问题,并且有一个非常简单的方法可以实现这一点:将包装pic
在一个矩阵中(只有一个条目)。您还可以为此编写一个宏,如下所示\ppic
。
\documentclass[tikz]{standalone}
\usetikzlibrary{positioning,calc,fit,shapes}
\tikzset {
factor/.style = {draw, ellipse},
indicator/.style = {draw, rectangle, outer sep=0},
arr/.style={-latex},
pics/collDown/.style n args={2}{
code={%
\node[indicator] ({#1}1) {{#1}};
\node[factor, above=2em of {#1}1] (#1) {#2};
\draw[arr] (#1) -- ({#1}1.north);
}
},
pics/collUp/.style n args={2}{
code={%
\node[indicator] ({#1}1) {{#1}};
\node[factor, below=2em of {#1}1] (#1) {#2};
\draw[arr] (#1) -- ({#1}1.south);
}
}
}
\begin{document}
\begin{tikzpicture}
\node[matrix] (a){\pic {collUp={A}{Some text}};\\};
\node[matrix,right=1em of a] (b) {\pic {collUp={B}{More text}};\\};
\node[matrix,below=1em of a] (c){\pic{collDown={C}{Weird stuff}};\\};
\node[matrix,below=1em of b] (d){\pic{collDown={D}{I'm giving up}};\\};
\end{tikzpicture}
\newcommand{\ppic}[2][]{
\node[matrix,#1]{\pic{#2};\\ };}
\begin{tikzpicture}
\ppic[local bounding box=a] {collUp={A}{Some text}};
\ppic[local bounding box=b, right=1em of a] {collUp={B}{More text}};
\ppic[local bounding box=c, below=1em of a] {collDown={C}{Weird stuff}};
\ppic[local bounding box=d, below=1em of b] {collDown={D}{I'm giving up}};
\end{tikzpicture}
\end{document}
如果您担心矩形不对齐,您可能需要统一椭圆的大小。
\documentclass[tikz]{standalone}
\usepackage{eqparbox}
\usetikzlibrary{positioning,calc,fit,shapes}
\newbox\eqnodebox
\tikzset{equal size/.style={execute at begin
node={\setbox\eqnodebox=\hbox\bgroup\vphantom{Hg}},
execute at end node={\egroup\eqmakebox[#1][c]{\copy\eqnodebox}}},
equal size/.default=A,
factor/.style = {draw, ellipse,equal size},
indicator/.style = {draw, rectangle, outer sep=0},
arr/.style={-latex},
pics/collDown/.style n args={2}{
code={%
\node[indicator] ({#1}1) {{#1}};
\node[factor, above=2em of {#1}1] (#1) {#2};
\draw[arr] (#1) -- ({#1}1.north);
}
},
pics/collUp/.style n args={2}{
code={%
\node[indicator] ({#1}1) {{#1}};
\node[factor, below=2em of {#1}1] (#1) {#2};
\draw[arr] (#1) -- ({#1}1.south);
}
}
}
\begin{document}
\begin{tikzpicture}
\node[matrix] (a){\pic {collUp={A}{Some text}};\\};
\node[matrix,right=1em of a] (b) {\pic {collUp={B}{More text}};\\};
\node[matrix,below=1em of a] (c){\pic{collDown={C}{Weird stuff}};\\};
\node[matrix,below=1em of b] (d){\pic{collDown={D}{I'm giving up}};\\};
\end{tikzpicture}
\end{document}
节点样式equal size
采用一个参数,可以将其视为指示器/标签。所有具有相同标签的节点组都将具有相同的宽度。
答案2
看了楼主的上述评论,我建议使用下面的代码(这是最简单的吗?)。一个简单的图形应该用一个简单的代码绘制。所有节点都是具有绝对定位的节点,但参数\a
、b
、\h
使代码变得灵活,也就是说,人们可以根据需要轻松控制距离。洋红色线用于检查水平对齐。
\documentclass[tikz,border=5mm]{standalone}
\usetikzlibrary{shapes}
\begin{document}
\begin{tikzpicture}[>=stealth]
\def\a{3.5} \def\b{4} \def\h{1.2}
\path[every node/.style={draw}]
(0,0) node (A) {A}
(\a,0) node (B) {B}
(0,-\b) node (C) {C}
(\a,-\b) node (D) {D};
\path[every node/.style={draw,ellipse}]
(A)+(-90:\h) node (At) {Some text}
(B)+(-90:\h) node (Bt) {More text}
(C)+(90:\h) node (Ct) {Weird stuff}
(D)+(90:\h) node (Dt) {I'm giving up};
\foreach \p in {A,B,C,D} \draw[->] (\p t)--(\p);
% check for horizontal alignment
\draw[cyan] (current bounding box.south west) rectangle (current bounding box.north east);
\draw[thin,magenta,shorten >=-1.2cm,shorten <=-1.2cm]
(A.base)--(B.base) (C.base)--(D.base)
(At.base)--(Bt.base) (Ct.base)--(Dt.base);
\end{tikzpicture}
\end{document}
更新正如 Kpym 所建议的,代码稍微短一些。
\documentclass[tikz,border=5mm]{standalone}
\usetikzlibrary{shapes}
\begin{document}
\begin{tikzpicture}\def\a{3.5} \def\b{4} \def\h{1.2}
\path[nodes=draw]
(0,0) node (A) {A} +(-90:\h) node[ellipse] (At) {Some text}
(\a,0) node (B) {B} +(-90:\h) node[ellipse] (Bt) {More text}
(0,-\b) node (C) {C} +(90:\h) node[ellipse] (Ct) {Weird stuff}
(\a,-\b) node (D) {D} +(90:\h) node[ellipse] (Dt) {I'm giving up};
\foreach \p in {A,B,C,D} \draw[-stealth] (\p t)--(\p);
\end{tikzpicture}
\end{document}
答案3
text depth
在所有节点上使用相同的解决方案
\documentclass[tikz]{standalone}
\usetikzlibrary{positioning,calc,fit,shapes}
\tikzset {
factor/.style = {draw, ellipse,text depth=0.2ex},
indicator/.style = {draw, rectangle, outer sep=0,text depth=0.2ex},
arr/.style={-latex},
pics/collDown/.style n args={2}{
code={%
\node[indicator] ({#1}1) {{#1}};
\node[factor, above=2em of {#1}1] (#1) {#2};
\draw[arr] (#1) -- ({#1}1.north);
}
},
pics/collUp/.style n args={2}{
code={%
\node[indicator] ({#1}1) {{#1}};
\node[factor, below=2em of {#1}1] (#1) {#2};
\draw[arr] (#1) -- ({#1}1.south);
}
}
}
\begin{document}
\begin{tikzpicture}
% \pic[local bounding box=a] {collUp={A}{Some text}};
% \pic[local bounding box=b, right=1em of a] {collUp={B}{More text}};
% \pic[local bounding box=c, below=1em of a] {collDown={C}{Weird stuff}};
% \pic[local bounding box=d, below=1em of b] {collDown={D}{I'm giving up}};
\pic at (0,-5) {collUp={A}{Some text}};
\pic at (3,-5) {collUp={B}{More text}};
\pic at (0,-9) {collDown={C}{Weird stuff}};
\pic at (3,-9) {collDown={D}{I'm giving up}};
\end{tikzpicture}
\end{document}