森林树,每个相对层级上都有文件夹

森林树,每个相对层级上都有文件夹

我想创建一棵树,其中每个分支的最后一个父节点的子节点被排列为一个文件夹。根据其他一些帖子,我创建了下面显示的示例。但是,这个示例的问题是,中心的文件夹(B.2.2.2、B.2.2.1 和 B.2.1)的水平距离异常大,因此节点重叠。

有没有什么方法可以调整这个空间,或者有没有更优雅的方法来在每个相对的最后一级创建文件夹(具有适当的对齐)?

\documentclass[border=10pt,multi,tikz]{standalone}
\usepackage[edges]{forest}
\usetikzlibrary{arrows.meta,shadows.blur,positioning,fit} 
\begin{document}
\begin{forest}
        forked edges,
        basic/.style = {draw, thin, drop shadow, font=\sffamily},
        upper style/.style = {basic, rounded corners=6pt, edge+={-Stealth, thin}, fill=black!6, text width=10.5em},
          lower style/.style = {basic, rounded corners=0pt, edge+={-, line width=.4pt}, fill=black!10, text width=9em},
          where n children=0{%
            lower style
          }{%
            upper style,
          },
          where level<=1{%
            parent anchor=children,
            child anchor=parent,
            if={isodd(n_children())}{%
              calign=child edge,
              calign primary child/.process={
                O+nw+n{n children}{(#1+1)/2}
              },
            }{%
              calign=edge midpoint,
            },
          }{
            grow'=0,
          },
           [{Root},fill=parent,
            [{A}, folder, grow'=0, for children={lower style},
              before drawing tree={
                tempdima/.option=!r2.max y,
                tempdima-/.option=max y,
                for tree={
                  y+/.register=tempdima,
                },
              }
                [A.1]
                [A.2]
                [...]
            ]
            [{B}, 
              [{B.1},   folder,   before drawing tree={
                tempdima/.option=!r2.max y,
                tempdima-/.option=max y,
                for tree={
                  y+/.register=tempdima,
                },
              }
                [B.1.1]
                [B.1.2]
              ]
              [{B.2},  grow'=south,  parent anchor=children,
            child anchor=parent,
            if={isodd(n_children())}{%
              calign=child edge,
              calign primary child/.process={
                O+nw+n{n children}{(#1+1)/2}
              },
            }{%
              calign=edge midpoint,
            },
                [{B.2.1},  folder,   before drawing tree={
                tempdima/.option=!r2.max y,
                tempdima-/.option=max y,
                for tree={
                  y+/.register=tempdima,
                },
              }
                    [B.2.1.2]
                    [B.2.1.3]
                    [B.2.1.4]
                    [B.2.1.5]
                    ]
              [{B.2.2}, grow'=south,parent anchor=children,
            child anchor=parent,calign=edge midpoint,
                [{B.2.2.1},  folder,   before drawing tree={
                tempdima/.option=!r2.max y,
                tempdima-/.option=max y,
                for tree={
                  y+/.register=tempdima,
                },
              }
                    [B.2.2.1.1]
                    [B.2.2.1.2]
                    [B.2.2.1.3]
                ]
                [{B.2.2.2},  folder,   before drawing tree={
                tempdima/.option=!r2.max y,
                tempdima-/.option=max y,
                for tree={
                  y+/.register=tempdima,
                },
              }
                    [B.2.2.2.1]
                    [B.2.2.2.2]
                    [B.2.2.2.3]
                ]
              ]]
              [{B.3},  folder,   before drawing tree={
                tempdima/.option=!r2.max y,
                tempdima-/.option=max y,
                for tree={
                  y+/.register=tempdima,
                },
              }  
                [B.3.1]
                [B.3.2]
                [B.3.3]
              ]
            ]
            [{C}, folder, grow'=0,
              before drawing tree={
                tempdima/.option=!r2.max y,
                tempdima-/.option=max y,
                for tree={
                  y+/.register=tempdima,
                },
              }
                [C.1]
                [C.2]
            ]
          ] 
\end{forest}
\end{document}

示例树

答案1

简短的回答:将(在节点和grow'=south上设置)更改为(不带撇号)。B.2B.2.2grow=south

美化(并可编译)的代码(带有一些注释):

\documentclass{standalone}

\usepackage[edges]{forest}
\usetikzlibrary{arrows.meta,shadows.blur}

\forestset{
  calign to midchild or edge midpoint/.style={
    if={isodd(n_children())}{
      calign=child edge,
      calign primary child/.process={
        O+nw+n{n children}{(##1+1)/2}
      },
    }{
      calign=edge midpoint,
    },
  },
}

\begin{document}
\begin{forest}
  forked edges,
  basic/.style = {draw, thin, drop shadow, font=\sffamily},
  upper style/.style = {basic, rounded corners=6pt, edge+={-Stealth, thin}, fill=black!6, text width=10.5em},
  lower style/.style = {basic, rounded corners=0pt, edge+={-, line width=.4pt}, fill=black!10, text width=9em},
  my fork/.style={
    grow=south, calign to midchild or edge midpoint,
  },
  my folder/.style={
    % This does not work but it should. The following release of Forest will fix the issue by changing "s+=tempdims()*(reversed()-0.5)*2," to "s+=tempdims()*(reversed("!parent")-0.5)*2," in the definition of style "folder".
    % grow'=0,
    % The workaround is to set "grow'" for the entire subtree.
    for tree={grow'=0},
    folder,
    % This code lifts the entire folder a little bit, but.
    % (a) It could do so more elegantly, by changing "l" before computing xy,
    % instead of changing "y" after computing xy.
    % (b) It relies on some accidental properties of the tree. "!r2" is the
    % second child of the root, which is "anchor"ed at the base by default, so
    % "max y" is the non-zero. The folder nodes are "anchor"ed on top, so their
    % "max y" is zero.  "tempdima" thus results in some, rather arbitrary
    % shift.
    % 
    % before drawing tree={
    %   tempdima/.option=!r2.max y,
    %   tempdima-/.option=max y,
    %   for tree={
    %     y+/.register=tempdima,
    %   },
    % }
    % 
    % A better way to do this is to explicitly shift the folder nodes by
    % changing their "l" at the right time.  Note that while this will work for
    % this tree, it could result in overlapping nodes in general (but the same
    %   was true for the approach above).
    before computing xy={l-=2.5ex},
  },
  for tree={
    parent anchor=children,
    child anchor=parent,
    if n children=0{
      lower style,
    }{
      upper style,
      % By default, we set "my fork" for all branching nodes.  We can do this
      % as everything it does is overriden by "my folder" (which is set
      %   manually for selected nodes).
      my fork,
    },
  },
  [Root,
    [A, my folder,
      [A.1]
      [A.2]
      [\dots]
    ]
    [B, 
      [B.1, my folder,
        [B.1.1]
        [B.1.2]
      ]
      [B.2,
        [B.2.1, my folder,
          [B.2.1.2]
          [B.2.1.3]
          [B.2.1.4]
          [B.2.1.5]
        ]
        [B.2.2,
          [B.2.2.1, my folder,
            [B.2.2.1.1]
            [B.2.2.1.2]
            [B.2.2.1.3]
          ]
          [B.2.2.2, my folder,
            [B.2.2.2.1]
            [B.2.2.2.2]
            [B.2.2.2.3]
          ]
        ]]
      [B.3, my folder,
        [B.3.1]
        [B.3.2]
        [B.3.3]
      ]
    ]
    [C, my folder, 
      [C.1]
      [C.2]
    ]
  ]
\end{forest}
\end{document}

结果

长答案。最大的问题是,如何使用growgrow'不是父母文件夹根目录会影响文件夹的外观吗?!

首先,与 不同growgrow'设置reversed为 true (请注意,在 OP 的图片中,B.2.1B.2.2是反转的, 和 也是如此B.2.2.1B.2.2.2

Style将父节点(即文件夹根节点)的folder设置为。这至关重要,因为样式会根据此参考点移动子节点,以产生文件夹的视觉效果。但是,锚点取决于它所用节点的父节点的(和)——在本例中是文件夹的父节点。(我必须考虑这是否是一个(设计)错误。)所以这里真正发生的事情是父节点(而不是子节点)被抛到了错误的位置。anchorparent firstparent firstreversedgrow

相关内容