我正在 tikz 中准备一个框图,如图所示1。我通过精确规划和计算距离和尺寸制作了这幅图。但是,对这幅图的任何更改都可能导致其他组件的更改。例如,如果我在 D 下方添加组件 D2,我必须相应地调整 E 和 F 的大小。
我的问题:您知道如何更好地解决这个问题吗?
具体来说,我希望有一种方法可以创建具有以下属性的图表:
- 可以根据其他组件的边缘定义物体的位置、高度和宽度(例如
E.north = B.north; E.south = D.south;
) - 灰色盒子正好适合其内容
- 白色矩形的最大尺寸为灰色框的 70%。同一行中的多个白色矩形均等共享可用宽度
- 数据库符号具有固定大小
- 当改变灰色框的位置时,其内容也会相应移动
- 中心常数(例如框高度、节点距离等)应定义一次,并且更改常数不应导致需要调整其他值
为了说明我当前的方法,这是显示大部分屏幕截图的代码:
\documentclass[tikz]{standalone}
\usetikzlibrary{shapes,fit,backgrounds,positioning,arrows,calc}
\begin{document}
\begin{tikzpicture}[font=\footnotesize,scale=0.9,->,>=stealth',shorten >=1pt,auto,semithick,
component/.style={draw,fill=white,inner xsep=1,minimum height=1.5em,node distance=.25cm and .5cm},
full/.style={minimum width=9cm},
full2/.style={minimum width=7.7cm},
half/.style={minimum width=4.25cm},
half2/.style={minimum width=3.6cm},
third/.style={minimum width=2.66cm},
layer_annot/.style={font=\footnotesize\bfseries,node distance=.5cm},
layer/.style={fill=lightgray,minimum width=\textwidth,minimum height=1.5em+.5cm,node distance=.5cm},
layer2/.style={minimum height=3em+.75cm},
layer4/.style={minimum height=6em+1.3cm},
spanv3/.style={minimum height=4.5em+.54cm},
db/.style={cylinder,draw,shape border rotate=90,fill=white,minimum width=.8cm,minimum height=.4cm,node distance=.5cm and .5cm,yshift=.3cm}]
% background
\begin{pgfonlayer}{background}
\node[layer,layer4] (F) {};
\node[layer,above=of F,layer2] (J) {};
\end{pgfonlayer}
% components
\node[component,full,below right=of F.north west] (A) {A};
\node[component,half2,below=of A.south east,anchor=north east] (B) {B};
\node[component,half2,below=of B] (C) {C};
\node[component,half2,below=of C] (D) {D};
\node[component,spanv3,half2,left=of B.north west,anchor=north east] (E) {E};
\node[db,left=of E.west] (db) {};
\node[component,full,below right=of J.north west] (G) {G};
\node[component,third,above right=of J.south west] (H) {H};
\node[component,third,right=of H] (I) {I};
% layer names
\node[layer_annot,left=of F.east] (F_label) {F};
\node[layer_annot,left=of J.east] (J_label) {J};
% connections
\path[->] ($(db -| E.west)+(0,.1)$) edge ($(db.east)+(0,.1)$)
($(db.east)-(0,.1)$) edge ($(db -| E.west)-(0,.1)$)
($(B -| E.east)+(0,.1)$) edge ($(B.west)+(0,.1)$)
($(B.west)-(0,.1)$) edge ($(B -| E.east)-(0,.1)$)
% ...
(E.north) edge (E.north |- A.south)
(A.north -| H.south) edge (H.south)
(A.north -| I.south) edge (I.south)
% ...
;
\end{tikzpicture}
\end{document}
答案1
我不明白你最后一条评论。不过,这个答案解决了如何
fit
通过和绘制背景矩形- 如何使用使节点与 和节点一样
E
高。(请注意,有一个硬编码,可以通过使用变换形状来消除,但我不知道你图片中的 的用途,所以我选择了这种方式)。B
C
D
calc
0.9
scale=0.9
这是代码。我不需要添加任何库,因为您正在加载但不使用fit
和calc
。
\documentclass[tikz]{standalone}
\usetikzlibrary{shapes,fit,backgrounds,positioning,arrows,calc}
\begin{document}
\begin{tikzpicture}[font=\footnotesize,scale=0.9,->,>=stealth',shorten >=1pt,auto,semithick,
component/.style={draw,fill=white,inner xsep=1,minimum height=1.5em,node distance=.25cm and .5cm},
full/.style={minimum width=9cm},
full2/.style={minimum width=7.7cm},
half/.style={minimum width=4.25cm},
half2/.style={minimum width=3.6cm},
third/.style={minimum width=2.66cm},
layer_annot/.style={font=\footnotesize\bfseries,node distance=.5cm},
layer/.style={fill=lightgray,minimum width=\textwidth,minimum height=1.5em+.5cm,node distance=.5cm},
layer2/.style={minimum height=3em+.75cm},
layer4/.style={minimum height=6em+1.3cm},
spanv3/.style={minimum height=4.5em+.54cm},
db/.style={cylinder,draw,shape border rotate=90,fill=white,minimum width=.8cm,minimum height=.4cm,node distance=.5cm and .5cm,yshift=.3cm}]
% components
\node[component,full] at (0,0) (A) {A};
\node[component,half2,below=of A.south east,anchor=north east] (B) {B};
\node[component,half2,below=of B] (C) {C};
\node[component,half2,below=of C] (D) {D};
\path let \p1=($(B.north)-(D.south)$) in \pgfextra{\typeout{\y1}}
node[component,minimum height=0.9*\y1,inner ysep=0pt,half2,left=of B.north west,anchor=north east] (E) {E};
\node[db,left=of E.west] (db) {};
\node[component,third,above=1.6cm of A.west,anchor=west] (H) {H};
\node[component,third,right=of H] (I) {I};
\node[component,full,above=8mm of H.west,anchor=west] (G) {G};
% background
\begin{pgfonlayer}{background}
\path ([xshift=3cm]D.east) coordinate(auxD) ([xshift=3cm]G.east) coordinate
(auxG);
\node[layer,fit=(A) (D) (auxD),layer4] (F) {};
\node[layer,fit=(G) (H) (auxG),layer2] (J) {};
\end{pgfonlayer}
% layer names
\node[layer_annot,left=of F.east] (F_label) {F};
\node[layer_annot,left=of J.east] (J_label) {J};
% connections
\path[->] ($(db -| E.west)+(0,.1)$) edge ($(db.east)+(0,.1)$)
($(db.east)-(0,.1)$) edge ($(db -| E.west)-(0,.1)$)
($(B -| E.east)+(0,.1)$) edge ($(B.west)+(0,.1)$)
($(B.west)-(0,.1)$) edge ($(B -| E.east)-(0,.1)$)
% ...
(E.north) edge (E.north |- A.south)
(A.north -| H.south) edge (H.south)
(A.north -| I.south) edge (I.south)
% ...
;
\end{tikzpicture}
\end{document}