当我使用 TiKz 绘制两棵树时,每棵树都在一个嵌套的图片中,第二棵树的中间子树的位置与第一棵树不同。尽管树的代码基本相同(除了 right=of 测试参数)。
我做错什么了吗?有没有办法解决这个问题,让两个中间的孩子都直接位于各自父母的领导下?
代码:
\documentclass{minimal}
\usepackage{tikz}
\usetikzlibrary{positioning}
\begin{document}
\begin{tikzpicture}
\tikzstyle{every node}=[draw]
\node (test) {
\begin{tikzpicture}
\node {}
child { node {} }
child { node {} }
child { node {} };
\end{tikzpicture}
};
\node [right=of test] {
\begin{tikzpicture}
\node {}
child { node {} }
child { node {} }
child { node {} };
\end{tikzpicture}
};
\end{tikzpicture}
\end{document}
答案1
作为Qrrbrbirlbel 解释 forest
可以与根一起使用phantom
,并提供用于指定树布局的灵活选项。
但是,指定l sep
和并s sep
不能保证中心子节点与父节点对齐。如果节点内容的宽度不同,则可能会失败:
\begin{forest}
for tree={
l sep=1cm,
s sep=1cm,
draw,
align=center
}
[,phantom
[
[some text here]
[a multiline node\\in the middle]
[not much]
]
[
[this\\node\\needs\\five\\lines]
[this\\one\\only\\four]
[finally\\just\\three]
]
]
\end{forest}
发生这种情况的原因是s sep
仅指定了最小距离。可以强制设置s
为某个值,从而设置距离。但是,最好允许forest
找出最佳值,并只给它一些关于我们希望它做什么的提示。calign with current
指示forest
将当前子级与其父级对齐,这正是本例中所需要的。
\begin{forest}
for tree={
draw,
if={isodd(n_children())}{
for children={
if={
equal(n,int((1+n_children("!u"))/2))
}{calign with current}{}
}
}{},
align=center
}
[,phantom
[
[some text here]
[a multiline node\\in the middle]
[not much]
]
[
[this\\node\\needs\\five\\lines]
[this\\one\\only\\four]
[finally\\just\\three]
]
]
\end{forest}
它的工作原理是测试一个节点是否有奇数个子节点。如果是,那么中心子节点将与其父节点对齐:
但是,如果父节点的边指向子节点的北边,而不是穿过节点,效果会更好。添加可child anchor=north
实现此目的:
如果根节点也包含内容,并且这两种情况下内容的高度不同,则会抛出垂直对齐问题:
为了避免这种情况,我们可以使用tier
来确保给定级别的所有节点都垂直对齐。添加tier/.wrap pgfmath arg={tier #1}{level()}
,我们得到以下结果:
完整代码:
\documentclass[tikz,border=5pt,multi]{standalone}
\usepackage{forest}
\standaloneenv{forest}
\begin{document}
\begin{forest}
for tree={
draw,
if={isodd(n_children())}{
for children={
if={
equal(n,int((1+n_children("!u"))/2))
}{calign with current}{}
}
}{},
align=center,
child anchor=north,
tier/.wrap pgfmath arg={tier #1}{level()}
}
[,phantom
[left tree\\(needs additional explanation)
[some text here]
[a multiline node\\in the middle]
[not much]
]
[right tree
[this\\node\\needs\\five\\lines]
[this\\one\\only\\four]
[finally\\just\\three]
]
]
\end{forest}
\end{document}
应用于具有空节点的原始树,这也会产生更紧凑的结果:
\documentclass[tikz,border=5pt,multi]{standalone}
\usepackage{forest}
\standaloneenv{forest}
\begin{document}
\begin{forest}
for tree={
draw,
if={isodd(n_children())}{
for children={
if={
equal(n,int((1+n_children("!u"))/2))
}{calign with current}{}
}
}{},
align=center,
child anchor=north,
tier/.wrap pgfmath arg={tier #1}{level()}
}
[,phantom
[
[]
[]
[]
]
[
[]
[]
[]
]
]
\end{forest}
\end{document}
答案2
如果你将xshift=-4.3725cm, red
选项添加到正确的节点,你会得到
这里的问题是,转换会right=of test
潜入底层树(或类似的东西)。
嵌套 TikZ 图片从来都不是一个好主意。
根据你想要实现的目标,你可以做类似的事情
\begin{tikzpicture}[nodes=draw, node distance=4cm]
\node (test) {} child { node {} } child { node {} } child { node {} };
\node [right=of test] {} child { node {} } child { node {} } child { node {} };
\end{tikzpicture}
或者(在本质上,矩阵实际上是一个节点)
\begin{tikzpicture}[nodes=draw]
\matrix [column sep=1cm] {
\node {} child { node {} } child { node {} } child { node {} }; &
\node {} child { node {} } child { node {} } child { node {} }; \\
};
\end{tikzpicture}
使用forest
包(\usepackage{forest}
),你可以做这样的事情:
\begin{forest} /tikz/nodes=draw, for tree={l sep=1cm, s sep=1cm}
[,phantom
[ [][][]]
[ [][][]]
]
\end{forest}