编辑

编辑

这是使用 tikz 绘制的流程图。代码量很大。一些对象的位置是通过反复试验计算出来的。我该如何简化它。此外,如何使连接块 4 和波浪线的箭头变直?

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric, arrows}
\usetikzlibrary{decorations.pathreplacing,decorations.markings,snakes}
\tikzset
{ 
process/.style={rectangle, minimum width=2cm, minimum height=1cm, align=center, text width=2cm, draw},
connector/.style={circle, minimum width=1cm, minimum height=0.5cm, align=center, text width=1cm, draw},
arrow/.style={thick, ->, >=stealth},
database/.style={
      cylinder,
      shape border rotate=90,
      aspect=0.25,
      draw
    }
}  
\tikzset{snake it/.style={decorate, decoration=snake}}
\begin{document}
\begin{tikzpicture}
\node (p0){Layers in system xyz};
\node (a) [process, below of=p0, text width=6cm] {Block 1};
\node (b) [process, below of=a, yshift=-1cm, text width=6cm] {Block 2};
\node (c) [process, below of=b, yshift=-1cm, text width=6cm] {Block 3};
\node (d) [process, below of=c, yshift=-1cm, text width=6cm] {Block 4};
\node (e) [process, below of=d, yshift=-3cm, text width=6cm] {Block 5};
\node (f) [process, right of=e, xshift=7cm, text width=6cm] {Block 6};

\path (a.south) -- (a.south east) coordinate[pos=0.5] (a1);
\path (a.south) -- (a.south west) coordinate[pos=0.5] (a2);

\path (b.north) -- (b.north east) coordinate[pos=0.5] (b1);
\path (b.north) -- (b.north west) coordinate[pos=0.5] (b2);
\path (b.south) -- (b.south east) coordinate[pos=0.5] (b3);
\path (b.south) -- (b.south west) coordinate[pos=0.5] (b4);

\path (c.north) -- (c.north east) coordinate[pos=0.5] (c1);
\path (c.north) -- (c.north west) coordinate[pos=0.5] (c2);
\path (c.south) -- (c.south east) coordinate[pos=0.5] (c3);
\path (c.south) -- (c.south west) coordinate[pos=0.5] (c4);

\path (d.north) -- (d.north east) coordinate[pos=0.5] (d1);
\path (d.north) -- (d.north west) coordinate[pos=0.5] (d2);
\path (d.south) -- (d.south east) coordinate[pos=0.5] (d3);
\path (d.south) -- (d.south west) coordinate[pos=0.5] (d4);

\path [draw,snake it]  (-3,-9) -- node[right, xshift=4 cm] { n/w}(3,-9);

\draw[latex-] (a1) -- (b1);
\draw[latex-] (b2) -- (a2);
\draw[latex-] (b3) -- (c1);
\draw[latex-] (c2) -- (b4);
\draw[latex-] (c3) -- (d1);
\draw[latex-] (d2) -- (c4);
\draw[latex-] (1.5,-8.5) --  node[right] {hi} (d3);
\draw[latex-] (d4) -- (-1.5,-8.5);
\draw[latex-] (1.5,-10.5) -- (1.5,-9.5);
\draw[latex-] (-1.5,-9.5) -- (-1.5,-10.5);
\draw [dashed] (e.east) -- (f.west);

\node[database] (db1) at (-2,-13) {DB1};
\node[database] (db2) at (2,-13) {DB2};
\node[database] (db3) at (6,-13) {DB3};
\node[database] (db4) at (10,-13) {DB4};
\end{tikzpicture}
\end{document}

输出

答案1

这是对原始问题的回应,在图表被 OP 追溯扩展之前!

这使用chains库来创建标题、蛇形线,并使用单个循环创建 4 个块。主要块之间的箭头作为同一循环的一部分绘制。最后,按照相同的模式绘制往返于蛇形线的箭头。

\documentclass[tikz, border=20pt]{standalone}
\usetikzlibrary{chains,arrows.meta,decorations.pathmorphing}
\begin{document}
\begin{tikzpicture}
  [start chain=main going below, every on chain/.append style={align=center, text width=60mm, minimum height=10mm}, >={LaTeX[]}]
  \node [on chain] {Layers in system xyz};
  \foreach \i [remember=\i as \iprior] in {1,...,4}
  {
    \node (block \i) [on chain, draw] {Block \i};
    \ifnum\i>1
      \draw [->] (block \iprior.south) +(-15mm,0) coordinate (b\i) -- (block \i.north -| b\i);
      \draw [<-] (block \iprior.south) +(15mm,0) coordinate (k\i) -- (block \i.north -| k\i);
    \fi
  }
  \node (squiggle) [on chain] {};
  \draw [decorate, decoration={snake}] (squiggle.west) -- (squiggle.east);
  \draw [->] (block 4.south -| b4) -- (squiggle -| b4);
  \draw [<-] (block 4.south -| k4) -- (squiggle -| k4);
\end{tikzpicture}
\end{document}

用链条和环圈制作的浓缩图案

这可以进一步缩短,但我认为这样会变得不那么容易理解。

编辑

这是对原帖作者大量扩展图表后修改后的问题的回应。

同样,这将chains库与一些循环和一些条件一起使用。它还使用该quotes库使通过箭头添加节点变得更容易。它被设计为可扩展的,以便可以轻松地将标签添加到图中的任何箭头。

\documentclass[tikz, border=20pt]{standalone}
\usetikzlibrary{chains,arrows.meta,decorations.pathmorphing,quotes}
\begin{document}
\begin{tikzpicture}
  [start chain=main going below, every on chain/.append style={align=center, text width=60mm, minimum height=10mm}, >={LaTeX[]}, every edge quotes/.append style={midway, auto, font=\small}, every label/.append style={font=\small}]
  \node [on chain] {Layers in system xyz};
  \foreach \i [remember=\i as \iprior] in {1,...,6}
  {
    \ifnum\i=5
      \node (block s) [on chain, label=right:n/w] {};
      \draw [decorate, decoration={snake}] (block s.west) -- (block s.east);
    \else
      \ifnum\i>5
        \node (block \iprior) [on chain, draw] {Block \iprior};
      \else
        \node (block \i) [on chain, draw] {Block \i};
      \fi
    \fi
  }
  \foreach \i/\j/\k [remember=\i as \iprior (initially 1)] in {2//,3//,4//,s//hi,5//}
  {
    \draw (block \iprior.south) +(-15mm,0) coordinate (b\i) edge ["\j", ->] (block \i.north -| b\i);
    \draw (block \iprior.south) +(15mm,0) coordinate (k\i) edge ["\k", <-] (block \i.north -| k\i);
  }
  \node (block 6) [on chain=going right, draw, join=by {dashed}] {Block 6};
\end{tikzpicture}
\end{document}

更多连锁店

在底部添加啤酒桶留给读者作为练习。

编辑 编辑

添加啤酒桶:

啤酒桶

完整代码

\documentclass[tikz, border=20pt]{standalone}
\usetikzlibrary{chains,arrows.meta,decorations.pathmorphing,quotes,shapes.geometric}
\begin{document}
\begin{tikzpicture}
  [start chain=main going below, every on chain/.append style={align=center, text width=60mm, minimum height=10mm}, >={LaTeX[]}, every edge quotes/.append style={midway, auto, font=\small}, every label/.append style={font=\small}, database/.style={cylinder, shape border rotate=90, aspect=0.25, draw}]
  \node [on chain] {Layers in system xyz};
  \foreach \i [remember=\i as \iprior] in {1,...,6}
  {
    \ifnum\i=5
      \node (block s) [on chain, label=right:n/w] {};
      \draw [decorate, decoration={snake}] (block s.west) -- (block s.east);
    \else
      \ifnum\i>5
        \node (block \iprior) [on chain, draw] {Block \iprior};
      \else
        \node (block \i) [on chain, draw] {Block \i};
      \fi
    \fi
  }
  \foreach \i/\j/\k [remember=\i as \iprior (initially 1)] in {2//,3//,4//,s//hi,5//}
  {
    \draw (block \iprior.south) +(-15mm,0) coordinate (b\i) edge ["\j", ->] (block \i.north -| b\i);
    \draw (block \iprior.south) +(15mm,0) coordinate (k\i) edge ["\k", <-] (block \i.north -| k\i);
  }
  \node (block 6) [on chain=going right, draw, join=by {dashed}] {Block 6};
  \path [every node/.style=database] (b5 |- block 5.south) +(0,-10mm) node (db1) {DB1} (k5 |- db1) node {DB2} (block 6.south |- db1) +(-15mm,0) node (db3) {DB3} +(15mm,0) node {DB4};
\end{tikzpicture}
\end{document}

解释

从传递给的选项开始tikzpicture

  [start chain=main going below, 

这将创建一个名为 的链main,其方向向下。因此,添加的每个节点都将添加到前一个节点的下方。

every on chain/.append style={align=center, text width=60mm, minimum height=10mm},

每个使用该样式的节点on chain,即添加到任何类型的链中的每个节点都将具有给定的样式属性,即最小高度为 1 厘米、文本宽度为 6 厘米、文本对齐到中心。

>={LaTeX[]}, 

每个箭头尖默认都是这种类型(使用arrows.meta替换的库中的新语法arrows)。

every edge quotes/.append style={midway, auto, font=\small},

quotes库允许您说出诸如... edge ["great label"] ...作为简写的内容... edge node {great label} ...every edge quotes设置要应用于以这种方式指定的所有节点的样式。

every label/.append style={font=\small}, 

所有label节点都将使用小文本。

database/.style={cylinder, shape border rotate=90, aspect=0.25, draw}]

来自您代码的风格。

  \node [on chain] {Layers in system xyz};

链上的第一个节点称为main

  \foreach \i [remember=\i as \iprior] in {1,...,6}

用一个变量开始一个循环\i,该变量将取值1,然后2,然后 ... 6。在第一个循环之后, 的先前值\i将作为 可用\iprior。因此,当 时,将\i是。2\iprior1

  {% everything here to be repeated for each \i
    \ifnum\i=5

如果\i5,我们想创建特殊的蛇形物件,而不是块。我们称之为block s。我们像往常一样将其添加到链中。

      \node (block s) [on chain, label=right:n/w] {};
      \draw [decorate, decoration={snake}] (block s.west) -- (block s.east);
    \else

如果我们不处理特殊情况,那么我们区分两种情况:蛇之前的块和蛇之后的块。

      \ifnum\i>5% blocks after the snake i.e. block 5
        \node (block \iprior) [on chain, draw] {Block \iprior};

在这种情况下,我们想要的先前的值\i,因为尽管我们没有创建常规块,但\iprior我们的蛇却踩到了的值。\i

      \else% blocks before the snake i.e. blocks 1-4
        \node (block \i) [on chain, draw] {Block \i};
      \fi
    \fi
  }

完成1-5号方块和蛇的绘制。

  \foreach \i/\j/\k [remember=\i as \iprior (initially 1)] in {2//,3//,4//,s//hi,5//}

这里有三个变量。同样, 的先前值\i保存为\iprior。在循环的第一次迭代中,\iprior将等于1。我们从 开始\i2因为我们不希望箭头进出块 1 的顶部。

该语法a/b/c意味着设置\ia\jb\kci这里是绘制箭头进入和离开的块的编号,\j\k是这些箭头应采用的任何标签。

  {% repeat this set for each triplet of values \i, \j and \k
    \draw (block \iprior.south) +(-15mm,0) coordinate (b\i) edge ["\j", ->] (block \i.north -| b\i);
    \draw (block \iprior.south) +(15mm,0) coordinate (k\i) edge ["\k", <-] (block \i.north -| k\i);

这就是quotes使用这个东西的地方。它设置\j\k作为绘制箭头的标签节点。表示与( )(a -| b)位于同一架子上且位于与()位于同一地面点上方的点,即坐标从和坐标从。a-b|xbya

  }

完成三元组集合的循环。

  \node (block 6) [on chain=going right, draw, join=by {dashed}] {Block 6};

添加块 6,这意味着我们希望链条朝不同的方向发展,因此on chain我们说而不是on chain=going right。在这里,我们告诉 TikZ 使用一条线将块连接到前一个块dashed。(上面不能使用它,因为join不会给你 2 个箭头 - 只有 1 个。)

最后,在底部添加啤酒桶。这是使用|-上面解释的语法。

  \path [every node/.style=database] (b5 |- block 5.south) +(0,-10mm) 

x从坐标点b5(之前定义)开始,y然后block5.south向下 10 毫米。

node (db1) {DB1}

创建第一个数据库,并将其命名为db1

 (k5 |- db1) node {DB2}

将第二个数据库k5与第一个数据库对齐。

(块 6.南 |- db1)+(-15mm,0)节点(db3){DB3}

我们没有b6k6所以我们需要通过向左移动 15 毫米来手动调整左右以放置第三个数据库......

+(15mm,0) node {DB4};

向右 15 毫米处放置第四个。

答案2

这是另一个选项,不像cfr's answer。这里的主要思想是利用positioningcalc库来放置元素。可以使用更多的 lopps,但我决定牺牲简洁性来追求清晰度:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric, arrows,positioning,calc}
\usetikzlibrary{decorations.pathreplacing,decorations.markings,snakes}

\tikzset
{ 
process/.style={rectangle, minimum width=2cm, minimum height=1cm, align=center, text width=6cm, draw},
connector/.style={circle, minimum width=1cm, minimum height=0.5cm, align=center, text width=1cm, draw},
arr/.style={->, >=latex},
revarr/.style={<-, >=latex},
database/.style={
      cylinder,
      shape border rotate=90,
      aspect=0.25,
      draw
    },
}  
\tikzset{snake it/.style={decorate, decoration=snake}}

\begin{document}

\begin{tikzpicture}
\def\Shift{40pt}
\node (p0){Layers in system xyz};
\node (1) [process, below=of p0] {Block 1};
\node (2) [process, below=of 1] {Block 2};
\node (3) [process, below=of 2] {Block 3};
\node (4) [process, below=of 3] {Block 4};
\coordinate[below=1.3cm of 4] (5);
\node (6) [process, below=1.3cm of 5] {Block 5};
\node (7) [process, right=of 6] {Block 6};

\path[draw,snake it]  
  (3.south west|-5) -- (3.south east|-5) node[right] { n/w} ;

\foreach \Valor in {1,...,3}
{
  \draw[arr] 
    ([xshift=-\Shift]\Valor.south) -- ([xshift=-\Shift]\the\numexpr\Valor+1\relax.north);
  \draw[revarr] 
    ([xshift=\Shift]\Valor.south) -- ([xshift=\Shift]\the\numexpr\Valor+1\relax.north);
}

\draw[revarr,shorten >= 0.3cm] 
    ([xshift=-\Shift]4.south) -- ([xshift=-\Shift]5.north);
\draw[revarr,shorten <= 0.3cm] 
    ([xshift=-\Shift]5.south) -- ([xshift=-\Shift]6.north);
\draw[arr,shorten >= 0.3cm] 
    ([xshift=\Shift]4.south) -- ([xshift=\Shift]5.north);
\draw[arr,shorten <= 0.3cm] 
    ([xshift=\Shift]5.south) -- ([xshift=\Shift]6.north);
\draw[dashed]
  (6) -- (7);

\path
  node[database] 
    (db1) at ([yshift=-1cm] $(6.south west)!0.25!(6.south east) $ ) {DB1} 
  node[database] 
    (db2) at ([yshift=-1cm] $(6.south west)!0.75!(6.south east) $ ) {DB2}
  node[database] 
    (db3) at ([yshift=-1cm] $(7.south west)!0.25!(7.south east) $ ) {DB3}
  node[database] 
    (db4) at ([yshift=-1cm] $(7.south west)!0.75!(7.south east) $ ) {DB4};
\end{tikzpicture}

\end{document}

在此处输入图片描述

相关内容