我一直在修改著名的 Forest 示例:
并学到了很多东西——我的 OverLeaf 项目位于:
https://www.overleaf.com/17438108ktrzgqwkpgtz#/66278887/
我被几件事难住了——(a)最烦人的是,我连接第 2 级和第 1 级的线走在单个第 1 级节点的前面,而不是后面。(b)不那么烦人的是,我想让所有第 2 级和第 4 级框的宽度和高度相同。这似乎应该很简单,但我还没有找到方法。
欢迎提出任何建议。我还希望发布我的 Overleaf 文件的链接是可以接受的,而不是将所有代码粘贴到这里。但是,如果我错了,请告诉我,我会将其粘贴到这里。
谢谢,
韦恩
答案1
为了努力使森林法规从使用的起点变得更短,然而,可以为森林树编写更先进、更简洁的代码,正如你在回答中看到的那样成本加运费,比我的好多了:
- 部分基于第一版的优秀土拨鼠的回答(我太懒了,没有从背面复制操作码)
- 对于节点使用预定义样式(其中定义矩形节点的最小宽度),现在从其他答案已知更好的解决方案......
对于边缘我使用由定义的样式
edge={...}
\documentclass[border=5pt]{standalone} \title{The Forest Project} \usepackage{forest} \usetikzlibrary{arrows.meta, calc, shadows, shapes.geometric} \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} % not used %\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} \begin{forest} ellip/.append style={ellipse, inner color=col1in, outer color=col1out}, rect/.append style={rectangle, rounded corners=2pt, inner color=col2in, outer color=col2out, minimum width=2.7cm}, circ/.append style={circle, inner color=col8in, outer color=col8out}, diam/.append style={diamond, inner color=col5in, outer color=col5out}, for tree={ font=\sffamily\bfseries, line width=2pt, draw=linecol, % adds the border to all nodes align=center, child anchor=north, parent anchor=south, drop shadow, l sep+=12.5pt, s sep=0.1cm, edge={color=linecol, rounded corners=5pt, -{Stealth[length=10pt]}, line width=1pt}, edge path={ \noexpand\path[\forestoption{edge}] (!u.parent anchor) -- +(0,-10pt) -| (.child anchor)\forestoption{edge label}; }, where level={1}{ if n<={2}{ edge path={ \noexpand\path[\forestoption{edge}] (!u.west) -| (.child anchor)\forestoption{edge label}; } }{if n<={4}{ edge path={ \noexpand\path[\forestoption{edge}] (!u.south) -| (.child anchor)\forestoption{edge label}; } }{ edge path={ \noexpand\path[\forestoption{edge}] (!u.east) -| (.child anchor)\forestoption{edge label}; }, }} }{}, } [Full Data Set, ellip [Middle, rect [CFA, circ [Middle, rect [LR, diam] ] ] ] [Bottom Support, rect [CFA, circ [Bottom Support, rect [LR, diam] ] ] ] [Bottom Carry, rect [CFA, circ [Bottom Carry, rect [LR, diam] ] ] ] [Bottom Other, rect [CFA, circ [Bottom Other, rect [LR, diam] ] ] ] [Top, rect [CFA, circ [Top, rect [LR, diam] ] ] ] [Jungle, rect [CFA, circ [Jungle, rect [LR, diam] ] ] ] ] \end{forest} \end{document}
答案2
如果你想要简洁的代码...请谨慎对待你的愿望...
这是改编自marmot 的回答它删除了不必要的代码并使用当前的 Forest 使代码更加简洁、高效。
\documentclass[border=12pt]{standalone}
\usepackage{forest}
\usetikzlibrary{arrows.meta, shadows.blur}
\colorlet{mygreen}{green!75!black}
\colorlet{col1in}{red!30}
\colorlet{col1out}{red!40}
\colorlet{col2in}{mygreen!40}
\colorlet{col2out}{mygreen!50}
\colorlet{col5in}{blue!10}
\colorlet{col5out}{blue!20}
\colorlet{col8out}{orange!40}
\colorlet{col8in}{orange!20}
\colorlet{linecol}{blue!60}
\tikzset{% no point in making this a forest style
rect/.append style={rounded corners=2pt, minimum width=2.7cm, inner color=col2in, outer color=col2out},
}
\forestset{
declare toks={branch from}{parent anchor}
}
\begin{document}
\begin{forest}
for tree={
font=\sffamily\bfseries,
line width=2pt,
draw=linecol,
align=center,
child anchor=parent,
parent anchor=children,
blur shadow,
l sep'+=12.5pt,
s sep'=0.1cm,
edge+={linecol, rounded corners=5pt, -{Stealth[length=10pt]}, line width=1pt},
if={ > Ow+P {level}{isodd(#1)}}{rect}{
if level=2{circle, inner color=col8in, outer color=col8out}{
if level=4{diamond, inner color=col5in, outer color=col5out}{},
},
},
},
for nodewalk={1,n}{branch from=west},
for nodewalk={l,p}{branch from=east},
for children={edge path'/.process={Ow{branch from}{(!u.#1) -| (.child anchor)}}}
[Full Data Set, ellipse, inner color=col1in, outer color=col1out,
[Middle,
[CFA
[Middle
[LR]
]
]
]
[Bottom Support
[CFA
[Bottom Support
[LR]
]
]
]
[Bottom Carry
[CFA
[Bottom Carry
[LR]
]
]
]
[Bottom Other
[CFA
[Bottom Other
[LR]
]
]
]
[Top
[CFA
[Top
[LR]
]
]
]
[Jungle
[CFA
[Jungle
[LR]
]
]
]
]
\end{forest}
\end{document}
答案3
更新:@cfr 提出了几条改进代码的重要建议,我尝试实施它们。非常感谢!
至于历史:有一些拼写错误,\makebo
我刚刚把它改掉了,我对你提到的两个问题有建议。首先,我添加了(假设这些是相关级别,森林从 0 开始计数)
if level={1}{minimum width=2.7cm,rect, inner color=col2in, outer color=col2out}{},
if level={2}{circle, inner color=col8in, outer color=col8out}{},
if level={3}{minimum width=2.7cm,rect, inner color=col2in, outer color=col2out}{},
if level={4}{diamond, inner color=col5in, outer color=col5out}{},
使第 1 层和第 3 层的节点宽度相同。这样也可以避免你一遍又一遍地写同样的东西,比如Zarko 的回答。
我的答案的一个关键部分是使最上面的连接复杂化(我不知道为什么拼写检查器会抱怨“复杂化”,这是物理学中的标准术语;-)为了解决第一个问题,请参阅代码。我基本上区分了 3 种情况而不是 2 种情况。而且,感谢 @cfr,我改用了一种让你晚上睡得更好的语法:没有\noexpand
黑客,只有简单的森林代码,就像在森林库边缘中一样,我将其用作基础(但这里不需要加载)。对于左边的两个连接,我从东边开始,中间的两个从南边开始,剩下的两个从东边开始。
\documentclass[border=5pt]{standalone}
\title{The Forest Project}
\usepackage{forest}
\usetikzlibrary{arrows.meta, shapes.geometric, calc, shadows.blur}
\forestset{
declare dimen={crazy sep}{-10pt},
crazy edge'/.style={
edge path'={[color=linecol, rounded corners=5pt, -{Stealth[length=10pt]}, line width=1pt]
(!u.parent anchor) -- +(0,\forestoption{crazy sep}) -| (.child anchor)},
},
crazy edge/.style={
on invalid={fake}{!parent.parent anchor=children},
child anchor=parent,
crazy edge',
},
crazy edges/.style={for nodewalk={#1}{crazy edge}},
crazy edges/.default=tree,
}
\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}
\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{forest}
for tree={
font=\sffamily\bfseries,
line width=2pt,
draw=linecol, % adds the border to all boxes
align=center,
child anchor=north,
parent anchor=south,
blur shadow,
l sep+=12.5pt,
s sep=0.1cm,
crazy edges,
if level={1}{minimum width=2.7cm,rect, inner color=col2in, outer color=col2out}{},
if level={2}{circle, inner color=col8in, outer color=col8out}{},
if level={3}{minimum width=2.7cm,rect, inner color=col2in, outer color=col2out}{},
if level={4}{diamond, inner color=col5in, outer color=col5out}{},
if level={1}{
if n<={2}{
edge path'={
[color=linecol, rounded corners=5pt, -{Stealth[length=10pt]}, line width=1pt]
(!u.west) -| (.child anchor)
}
}{if n<={4}{
edge path'={
[color=linecol, rounded corners=5pt, -{Stealth[length=10pt]}, line width=1pt]
(!u.south) -| (.child anchor)
}
}{
edge path'={
[color=linecol, rounded corners=5pt, -{Stealth[length=10pt]}, line width=1pt]
(!u.east) -| (.child anchor)
},
}}
}{},
}
[Full Data Set, ellipse, inner color=col1in, outer color=col1out
[Middle,
[CFA
[Middle
[LR]
]
]
]
[Bottom Support
[CFA
[Bottom Support
[LR]
]
]
]
[Bottom Carry
[CFA
[Bottom Carry
[LR]
]
]
]
[Bottom Other
[CFA
[Bottom Other
[LR]
]
]
]
[Top
[CFA
[Top
[LR]
]
]
]
[Jungle
[CFA
[Jungle
[LR]
]
]
]
]
\end{forest}
\end{document}