编辑

编辑

此 MWE 代码改编自示例位于 www.texample.net,最初由 SE 用户编写成本加运费

\documentclass{article}

\usepackage{graphicx}
\usepackage{tikz}
\usetikzlibrary{arrows.meta, shapes.geometric, calc, shadows}
\usepackage{forest}
\usepackage{adjustbox}

\colorlet{mygreen}{green!75!black}
\colorlet{col1in}{red!30}
\colorlet{col1out}{red!40}
\colorlet{col2in}{mygreen!40}
\colorlet{col2out}{mygreen!50}
\colorlet{col3in}{blue!30}
\colorlet{col3out}{blue!40}
\colorlet{col4in}{mygreen!20}
\colorlet{col4out}{mygreen!30}
\colorlet{col5in}{blue!10}
\colorlet{col5out}{blue!20}
\colorlet{col6in}{blue!20}
\colorlet{col6out}{blue!30}
\colorlet{col7out}{orange}
\colorlet{col7in}{orange!50}
\colorlet{col8out}{orange!40}
\colorlet{col8in}{orange!20}
\colorlet{linecol}{blue!60}

\begin{document}

\tikzset{
  basic/.style  = {draw, drop shadow, rectangle},
  root/.style   = {basic, rounded corners=2pt, thin, align=center,
                   fill=green!30},
  level 2/.style = {basic, rounded corners=6pt, thin,align=center, fill=blue!10},
  level 3/.style = {basic, thin, align=left, fill=green!10}
}

\pgfkeys{/forest,
  rect/.append style   = {rectangle, rounded corners = 2pt,
                         inner color = col6in, outer color = col6out},
  ellip/.append style  = {ellipse, inner color = col5in,
                          outer color = col5out},
  orect/.append style  = {rect, font = \sffamily\bfseries\LARGE,
                         text width = 325pt, text centered,
                         minimum height = 10pt, outer color = col7out,
                         inner color=col7in},
  oellip/.append style = {ellip, inner color = col8in, outer color = col8out,
                          font = \sffamily\bfseries\large, text centered}}

\begin{figure}[h]
\begin{adjustbox}{max width=1.2\textwidth,center}    
    \begin{forest}
      for tree={
          font=\sffamily\bfseries,
          line width=1pt,
          draw=linecol,
          ellip,
          align=center,
          child anchor=north,
          parent anchor=south,
          drop shadow,
          l sep+=12.5pt,
          edge path={
            \noexpand\path[color=linecol, rounded corners=5pt,
              >={Stealth[length=10pt]}, line width=1pt, ->, \forestoption{edge}]
              (!u.parent anchor) -- +(0,-5pt) -|
              (.child anchor)\forestoption{edge label};
            },
          where level={3}{tier=tier3}{},
          where level={0}{l sep-=15pt}{},
          where level={1}{
            if n={1}{
              edge path={
                \noexpand\path[color=linecol, rounded corners=5pt,
                  >={Stealth[length=10pt]}, line width=1pt, ->,
                  \forestoption{edge}]
                  (!u.west) -| (.child anchor)\forestoption{edge label};
                },
            }{
              edge path={
                \noexpand\path[color=linecol, rounded corners=5pt,
                  >={Stealth[length=10pt]}, line width=1pt, ->,
                  \forestoption{edge}]
                  (!u.east) -| (.child anchor)\forestoption{edge label};
                },
            }
          }{},
      }
      [\Huge Total drag, yshift = 3cm, inner color=col1in, outer color=col1out
        [\huge Viscous drag, yshift = 1cm, inner color=col2in, outer color=col2out
          [\Large Displacement separation, inner color=col4in, outer color=col4out
          ]
          [\Large Boundary layer shear, inner color=col4in, outer color=col4out 
          ]
        ]
        [\huge Vortex drag, yshift = 1cm, inner color=col3in, outer color=col3out
          [\Large Trailing vortices due to lift
          ]
        ]
        [\huge Wave drag, yshift = 1cm, inner color=col3in, outer color=col3out
              [\Large Waves due to lift
              ]
              [\Large Waves due to volume
              ]
        ]  
        ]
       ]
    \end{forest}
    \end{adjustbox}
    \end{figure}
    \end{document}

产生这个:

在此处输入图片描述

我如何添加一个大的水平花括号来为所有底部节点添加注释,以获得如下效果:

在此处输入图片描述

答案1

Heiko Oberdiek 的回答是一种很好的方法,但另一种方法是将添加指定为树本身规范的一部分。在这种情况下,您可以使用相对节点名称来处理定位。

请注意,该backgrounds库不需要解决在根节点上绘制边缘路径的问题。该问题只是由于未指定第一级中的 2 条非标准路径应仅适用于第一个和最后一个节点 - 而不是中间节点。检查节点是第一个还是最后一个可以解决问题,然后使用中间节点与父节点对齐,calign with current因此路径根本不会发生任何奇怪的事情。

您的代码包含大量不必要的负担。虽然orect在首次创建时可能是一种非常有用的样式,但实际上对您来说并没有多大用处。多余的负担还会导致一些方法,例如首先减少级别之间的间隔,然后手动移动每个级别内的每个节点以增加间隔。这使得事情更有可能无法按您的预期进行,并且更难找出原因,同时也给您带来更多工作。

我删除了大量多余的内容。显然,您的原始图表可能需要添加其中的一些内容,但我非常怀疑它是否需要全部添加,并且不可能要求执行 X 然后在几行之后撤消 X。

无论如何,这是我的版本:

使用相对节点名称将括号作为树的一部分

支架本身就是一种装饰品,就像Heiko 的回答,但装饰是与树的根节点一起指定的,使用tikz键:

tikz={\draw [decorate, line width=2.5pt, decoration={brace, mirror, amplitude=10mm}] (!F.south -| !F.west) +(0,-5mm) coordinate (a) -- (a -| !L.east) node [midway, below=15mm, Large] {bla bla bla} ;}

!F指相对于当前(根)节点的第一个叶节点;!L指最后一个叶节点。由于椭圆的西南点和东南点位于其边界上,因此这些节点的southwesteast锚点用于放置。

Large是为了方便而定义的样式,相当于font=\sffamily\bfseries\Large

通过将大部分格式打包到样式中,树的结构从指定它的代码中更加明显。(我们tikz也可以将括号的规范放在树的序言中,但我在这里没有费心。)

\documentclass[tikz,border=10pt]{standalone}

\usetikzlibrary{arrows.meta, decorations.pathreplacing, shadows}
\usepackage{forest}

\colorlet{mygreen}{green!75!black}
\colorlet{col1in}{red!30}
\colorlet{col1out}{red!40}
\colorlet{col2in}{mygreen!40}
\colorlet{col2out}{mygreen!50}
\colorlet{col3in}{blue!30}
\colorlet{col3out}{blue!40}
\colorlet{col4in}{mygreen!20}
\colorlet{col4out}{mygreen!30}
\colorlet{col5in}{blue!10}
\colorlet{col5out}{blue!20}
\colorlet{linecol}{blue!60}

\begin{document}

\tikzset{
  ellip/.append style  = {ellipse, col in out = 5},
  col in out/.style = {inner color = col#1in, outer color = col#1out},
  font sizing/.style={font=\sffamily\bfseries#1},
  Huge/.style={font sizing=\Huge},
  huge/.style={font sizing=\huge},
  Large/.style={font sizing=\Large},
}

\begin{forest}
  for tree={
      font=\sffamily\bfseries,
      line width=1pt,
      draw=linecol,
      ellip,
      align=center,
      child anchor=north,
      parent anchor=south,
      drop shadow,
      l sep+=10mm,
      edge={color=linecol, rounded corners=5pt, >={Stealth[length=10pt]}, line width=1pt, ->},
      edge path={% this is the default code for the edge from parent to child
        \noexpand\path[\forestoption{edge}] (!u.parent anchor) -- +(0,-5pt) -| (.child anchor)\forestoption{edge label};
        },
      if level=1{
        huge,
        if n=1{
          col in out=2,
          for children={col in out=4},
          edge path={% this overrides the path from parent to child for this particular case i.e. level is 1 and child is first (n=1)
            \noexpand\path[\forestoption{edge}] (!u.west) -| (.child anchor)\forestoption{edge label};
            },
        }{
          col in out=3,
          if n'=1{
            edge path={% this overrides the path from parent to child for this particular case i.e. level is 1 and child is last (n'=1)
              \noexpand\path[\forestoption{edge}] (!u.east) -| (.child anchor)\forestoption{edge label};
            },
          }{% if the child is neither the first one nor the last one, it must be the middle one, so align the parent with this one to avoid kinks in the edge path in this case
            calign with current
          }
        }
      }{},
      if level=2{Large}{}
  }
  [Total drag, Huge, col in out=1, tikz={\draw [decorate, line width=2.5pt, decoration={brace, mirror, amplitude=10mm}] (!F.south -| !F.west) +(0,-5mm) coordinate (a) -- (a -| !L.east) node [midway, below=15mm, Large] {bla bla bla} ;}
    [Viscous drag
      [Displacement separation
      ]
      [Boundary layer shear
      ]
    ]
    [Vortex drag
      [Trailing vortices due to lift
      ]
    ]
    [Wave drag
          [Waves due to lift
          ]
          [Waves due to volume
          ]
    ]
   ]
\end{forest}
\end{document}

编辑

为了响应注释中对每个终端节点下括号的请求,我们可以定义一个under label接受一个参数的样式,该参数是在括号下方要打印的文本:

许多括号

完整代码:

\documentclass[tikz,border=10pt]{standalone}

\usetikzlibrary{arrows.meta, decorations.pathreplacing, shadows}
\usepackage{forest}

\colorlet{mygreen}{green!75!black}
\colorlet{col1in}{red!30}
\colorlet{col1out}{red!40}
\colorlet{col2in}{mygreen!40}
\colorlet{col2out}{mygreen!50}
\colorlet{col3in}{blue!30}
\colorlet{col3out}{blue!40}
\colorlet{col4in}{mygreen!20}
\colorlet{col4out}{mygreen!30}
\colorlet{col5in}{blue!10}
\colorlet{col5out}{blue!20}
\colorlet{linecol}{blue!60}

\begin{document}

\tikzset{
  ellip/.append style  = {ellipse, col in out = 5},
  col in out/.style = {inner color = col#1in, outer color = col#1out},
  font sizing/.style={font=\sffamily\bfseries#1},
  Huge/.style={font sizing=\Huge},
  huge/.style={font sizing=\huge},
  Large/.style={font sizing=\Large},
}
\forestset{
  under label/.style = {
    tikz={\draw [decorate, line width=2.5pt, decoration={brace, mirror, amplitude=10mm}] (.south -| .west) +(0,-2.5mm) coordinate (a) -- (a -| .east) node [midway, below=12.5mm, Large] {#1} ;}
  }
}

\begin{forest}
  for tree={
      font=\sffamily\bfseries,
      line width=1pt,
      draw=linecol,
      ellip,
      align=center,
      child anchor=north,
      parent anchor=south,
      drop shadow,
      l sep+=10mm,
      edge={color=linecol, rounded corners=5pt, >={Stealth[length=10pt]}, line width=1pt, ->},
      edge path={% this is the default code for the edge from parent to child
        \noexpand\path[\forestoption{edge}] (!u.parent anchor) -- +(0,-5pt) -| (.child anchor)\forestoption{edge label};
        },
      if level=1{
        huge,
        if n=1{
          col in out=2,
          for children={col in out=4},
          edge path={% this overrides the path from parent to child for this particular case i.e. level is 1 and child is first (n=1)
            \noexpand\path[\forestoption{edge}] (!u.west) -| (.child anchor)\forestoption{edge label};
            },
        }{
          col in out=3,
          if n'=1{
            edge path={% this overrides the path from parent to child for this particular case i.e. level is 1 and child is last (n'=1)
              \noexpand\path[\forestoption{edge}] (!u.east) -| (.child anchor)\forestoption{edge label};
            },
          }{% if the child is neither the first one nor the last one, it must be the middle one, so align the parent with this one to avoid kinks in the edge path in this case
            calign with current
          }
        }
      }{},
      if level=2{Large}{}
  }
  [Total drag, Huge, col in out=1
    [Viscous drag
      [Displacement separation, under label={The why}
      ]
      [Boundary layer shear, under label={The what}
      ]
    ]
    [Vortex drag
      [Trailing vortices due to lift, under label={The how}
      ]
    ]
    [Wave drag
      [Waves due to lift, under label={Sufficient explanation}
      ]
      [Waves due to volume, under label={Necessary information}
      ]
    ]
   ]
\end{forest}
\end{document}

答案2

可以将附加 TikZ 材料放在\end{forest}

 \usetikzlibrary{decorations, decorations.pathmorphing} % in the preamble

  % inside environment forest
  \draw[thick, decorate, decoration={brace, amplitude=1.5em}]
      ([yshift=-.5em]current bounding box.south east) --
      node[below=2em, font=\sffamily\bfseries\Large]
        {Bla bla bla}
      ([yshift=-.5em]current bounding box.south west)
   ;
\end{forest}

大括号作为装饰来绘制brace。由于大括号覆盖了图像底部的整个宽度,因此可以使用当前边界框来跨越整个宽度。

通过使用库将线放在背景层上,可以解决根节点上方线的问题backgrounds

  edge path={
    \noexpand\scoped[on background layer]
    \noexpand\path[color=linecol, rounded corners=5pt,
      >={Stealth[length=10pt]}, line width=1pt, ->,
      \forestoption{edge}, on background layer]
      (!u.east) -| (.child anchor)\forestoption{edge label};
    },

完整示例:

\documentclass{article}

\usepackage{graphicx}
\usepackage{tikz}
\usetikzlibrary{arrows.meta, shapes.geometric, calc, shadows}
\usetikzlibrary{decorations, decorations.pathreplacing}
\usetikzlibrary{backgrounds}
\usepackage{forest}
\usepackage{adjustbox}

\colorlet{mygreen}{green!75!black}
\colorlet{col1in}{red!30}
\colorlet{col1out}{red!40}
\colorlet{col2in}{mygreen!40}
\colorlet{col2out}{mygreen!50}
\colorlet{col3in}{blue!30}
\colorlet{col3out}{blue!40}
\colorlet{col4in}{mygreen!20}
\colorlet{col4out}{mygreen!30}
\colorlet{col5in}{blue!10}
\colorlet{col5out}{blue!20}
\colorlet{col6in}{blue!20}
\colorlet{col6out}{blue!30}
\colorlet{col7out}{orange}
\colorlet{col7in}{orange!50}
\colorlet{col8out}{orange!40}
\colorlet{col8in}{orange!20}
\colorlet{linecol}{blue!60}

\begin{document}

\tikzset{
  basic/.style  = {draw, drop shadow, rectangle},
  root/.style   = {basic, rounded corners=2pt, thin, align=center,
                   fill=green!30},
  level 2/.style = {basic, rounded corners=6pt, thin,align=center, fill=blue!10},
  level 3/.style = {basic, thin, align=left, fill=green!10}
}

\pgfkeys{/forest,
  rect/.append style   = {rectangle, rounded corners = 2pt,
                         inner color = col6in, outer color = col6out},
  ellip/.append style  = {ellipse, inner color = col5in,
                          outer color = col5out},
  orect/.append style  = {rect, font = \sffamily\bfseries\LARGE,
                         text width = 325pt, text centered,
                         minimum height = 10pt, outer color = col7out,
                         inner color=col7in},
  oellip/.append style = {ellip, inner color = col8in, outer color = col8out,
                          font = \sffamily\bfseries\large, text centered}}

\begin{figure}[h]
\begin{adjustbox}{max width=1.2\textwidth,center}    
    \begin{forest}
      for tree={
          font=\sffamily\bfseries,
          line width=1pt,
          draw=linecol,
          ellip,
          align=center,
          child anchor=north,
          parent anchor=south,
          drop shadow,
          l sep+=12.5pt,
          edge path={
            \noexpand\path[color=linecol, rounded corners=5pt,
              >={Stealth[length=10pt]}, line width=1pt, ->, \forestoption{edge}]
              (!u.parent anchor) -- +(0,-5pt) -|
              (.child anchor)\forestoption{edge label};
            },
          where level={3}{tier=tier3}{},
          where level={0}{l sep-=15pt}{},
          where level={1}{
            if n={1}{
              edge path={
                \noexpand\path[color=linecol, rounded corners=5pt,
                  >={Stealth[length=10pt]}, line width=1pt, ->,
                  \forestoption{edge}]
                  (!u.west) -| (.child anchor)\forestoption{edge label};
                },
            }{
              edge path={
                \noexpand\scoped[on background layer]
                \noexpand\path[color=linecol, rounded corners=5pt,
                  >={Stealth[length=10pt]}, line width=1pt, ->,
                  \forestoption{edge}, on background layer]
                  (!u.east) -| (.child anchor)\forestoption{edge label};
                },
            }
          }{},
      }
      [\Huge Total drag, yshift = 3cm, inner color=col1in, outer color=col1out
        [\huge Viscous drag, yshift = 1cm, inner color=col2in, outer color=col2out
          [\Large Displacement separation, inner color=col4in, outer color=col4out
          ]
          [\Large Boundary layer shear, inner color=col4in, outer color=col4out 
          ]
        ]
        [\huge Vortex drag, yshift = 1cm, inner color=col3in, outer color=col3out
          [\Large Trailing vortices due to lift
          ]
        ]
        [\huge Wave drag, yshift = 1cm, inner color=col3in, outer color=col3out
              [\Large Waves due to lift
              ]
              [\Large Waves due to volume
              ]
        ]  
        ]
       ]
       %
       \draw[thick, decorate, decoration={brace, amplitude=1.5em}]
          ([yshift=-.5em]current bounding box.south east) --
          node[below=2em, font=\sffamily\bfseries\Large]
            {Bla bla bla}
          ([yshift=-.5em]current bounding box.south west)
       ;
    \end{forest}
\end{adjustbox}
\end{figure}
\end{document}

结果

答案3

您可以使用 tikz 中的装饰来添加括号。

\usetikzlibrary{decorations.pathreplacing}

\draw [decorate,decoration=brace,mirror,amplitude=20pt},xshift=-1em,yshift=-2em](-20,-2) -- (20,-2) node [black,midway,yshift=-3em]{\footnotesize blahblah};

mirror翻转支架的方向(若没有它,支架则指向上方)。

amplitude确定支撑的深度(因为它是水平的而不是垂直的)。

相关内容