我想要一个垂直时间轴,如下图所示,但我有两个相关问题,我不知道如何解决。
我希望轴出现在树的左侧,偏移特定量,比如说最左侧分支(或叶节点标签;例如本例中的灰狐狸)左侧 1 厘米。好的,现在,我必须通过反复试验找到距离。随着树的大小发生变化(添加或删除节点),轴的位置应相应调整。
我希望轴的长度能够自动适应树的高度。现在,我手动计算层数并乘以值
l set
(本例中为 1 厘米)。
这两者都可以通过编程来确定吗?
\documentclass{article}
\usepackage{forest}
\usetikzlibrary{positioning, backgrounds}
\tikzset{
timeline/.style={align=right, text width=2cm},
no edge from this parent/.style={
every child/.append style={
edge from parent/.style={draw=none}}},
}
\forestset{
every leaf node/.style={
if n children=0{\raggedright #1}{}
},
every tree node/.style={
if n children=0{}{#1}
},
mytree/.style={
for tree={
edge path={
\noexpand\path [draw, ultra thick, \forestoption{edge}] (!u.parent anchor) -| (.child anchor)\forestoption{edge label};
},
every tree node={draw=none,inner sep=0, outer sep=0, minimum size=0},
every leaf node/.style={align=right},
grow'=north,
parent anchor=north,
child anchor=south,
anchor=base,
l sep=1cm,
s sep=3mm,
draw=none,
if n children=0{tier=word, align=center, base=bottom}{}
}
}
}
\begin{document}
\begin{forest} mytree
[, name=lvl0
[,name=lvl1
[,name=lvl2
[gray fox]
[island fox]
]
[
[,name=lvl3
[black\\bear]
[giant\\panda]
]
[
[northern\\elephant\\seal]
[walrus]
]
]
]
]
%
\coordinate (tml) at (-6.5,0);
\begin{scope}[on background layer]
\draw (-5.3,0) -- (-5.3,4) node [above] {\textsc{mya}};
\foreach \x/\age/\len in {1/10/2, 2/7.4/4, 3/4/4}
{
\node[timeline] (age\x) at (lvl\x -| tml) {\age};
\draw[gray, thick, dotted] (age\x) -- (lvl\x);
}
\end{scope}
\end{forest}
\end{document}
答案1
像这样吗?
\documentclass[border=10pt,multi,tikz]{standalone}
\usepackage{forest}
\usetikzlibrary{backgrounds}
\forestset{
declare dimen register={timeline offset},
timeline offset'=10mm,
declare toks register={timeline target},
timeline target=,
declare boolean={tree node}{0},
mytree/.style={
for tree={
edge+={ultra thick},
edge path'={
(!u.parent anchor) -| (.child anchor)
},
grow'=north,
parent anchor=children,
child anchor=parent,
anchor=base,
l sep=1cm,
s sep=3mm,
if n children=0{tier=word, align=center, base=bottom, not tree node}{coordinate, tree node}
}
},
timeline/.style={
before drawing tree={
timeline target/.option=name,
tempdima/.option=y,
for tree={
if={>OR>{y}{tempdima}}{timeline target/.option=name}{},
}
},
tikz+={
\begin{scope}[on background layer]
\draw ([xshift=-\foresteregister{timeline offset}]current bounding box.west |- .parent anchor) coordinate (timeline base) -- (\foresteregister{timeline target}.child anchor -| timeline base) node [above] {\textsc{mya}};
\end{scope}
},
},
}
\begin{document}
\begin{forest}
mytree,
timeline
[, name=lvl0
[,name=lvl1
[,name=lvl2
[gray fox]
[island fox]
]
[
[,name=lvl3
[black\\bear]
[giant\\panda]
]
[
[northern\\elephant\\seal]
[walrus]
]
]
]
]
\begin{scope}[on background layer]
\foreach \x/\age/\len in {1/10/2, 2/7.4/4, 3/4/4}
{
\node [anchor=east] (age\x) at (lvl\x -| timeline base) {\age};
\draw [gray, thick, dotted] (age\x) -- (lvl\x);
}
\end{scope}
\end{forest}
\end{document}
编辑
这是一个略有不同的版本,它允许您说出age=<value>
树中的节点,然后自动完成其余操作。至少,理论上是这样的。
\documentclass[border=10pt,multi,tikz]{standalone}
\usepackage{forest}
\usetikzlibrary{backgrounds}
\forestset{
declare dimen register={timeline offset},
timeline offset'=10mm,
declare toks register={timeline target},
timeline target=,
declare boolean={tree node}{0},
age/.code={
\pgfkeys{/level age \foresteoption{level}/.initial={#1}}
},
mytree/.style={
for tree={
edge+={ultra thick},
edge path'={
(!u.parent anchor) -| (.child anchor)
},
grow'=north,
parent anchor=children,
child anchor=parent,
anchor=base,
l sep=1cm,
s sep=3mm,
if n children=0{tier=word, align=center, base=bottom, not tree node}{coordinate, tree node}
}
},
timeline/.style={
before drawing tree={
timeline target/.option=name,
tempdima/.option=y,
for tree={
if={>OR>{y}{tempdima}}{timeline target/.option=name}{},
},
tempcounta/.option=level,
for nodewalk={
filter={tree breadth-first}{>On>{n children}{0}}%
}{
if={
>OR>{level}{tempcounta}%
}{
tempcounta/.option=level,
tikz+={
\edef\tempa{level age \foresteoption{level}}
\begin{scope}[on background layer]
\pgfkeys{/level age \foresteoption{level}/.get=\mylevelage}
\draw [draw=gray, thick, dotted] () -- ( -| timeline base) node [left, anchor=east] {\mylevelage};
\end{scope}
}%
}{}
},
},
tikz+={
\begin{scope}[on background layer]
\draw ([xshift=-\foresteregister{timeline offset}]current bounding box.west |- .parent anchor) coordinate (timeline base) -- (\foresteregister{timeline target}.child anchor -| timeline base) node [above] {\textsc{mya}};
\end{scope}
},
},
}
\begin{document}
\begin{forest}
mytree,
timeline
[
[, age=10
[
[gray fox]
[island fox, age=4]
]
[, age=7.4
[
[black\\bear]
[giant\\panda]
]
[
[northern\\elephant\\seal]
[walrus]
]
]
]
]
\end{forest}
\end{document}
输出如上。