我想创建一棵树,其中每个分支的最后一个父节点的子节点被排列为一个文件夹。根据其他一些帖子,我创建了下面显示的示例。但是,这个示例的问题是,中心的文件夹(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.2
B.2.2
grow=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}
长答案。最大的问题是,如何使用grow
而grow'
不是父母文件夹根目录会影响文件夹的外观吗?!
首先,与 不同grow
,grow'
设置reversed
为 true (请注意,在 OP 的图片中,B.2.1
和B.2.2
是反转的, 和 也是如此B.2.2.1
)B.2.2.2
。
Style将父节点(即文件夹根节点)的folder
设置为。这至关重要,因为样式会根据此参考点移动子节点,以产生文件夹的视觉效果。但是,锚点取决于它所用节点的父节点的(和)——在本例中是文件夹的父节点。(我必须考虑这是否是一个(设计)错误。)所以这里真正发生的事情是父节点(而不是子节点)被抛到了错误的位置。anchor
parent first
parent first
reversed
grow