我正在尝试制作一棵树,其边缘有两种不同的颜色,黑色和灰色。这是我的代码:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning,automata}
\definecolor{light-gray}{gray}{0.6}
\begin{document}
\begin{tikzpicture}[line width=.1cm,shorten >=0pt,auto,on grid=false, every state/.style={minimum size=0pt}, level distance=2.0cm, level 1/.style={sibling distance=2cm}, level 2/.style={sibling distance=1cm}, level 3/.style={sibling distance=.5cm}]
\tikzstyle{every node}=[font=\tiny , circle, outer sep=0pt, inner sep=0pt]
\node[] (S) {}
child {node[state] (S1) {}
child {node[state] (S11) {} edge from parent[light-gray] }
child {node[state] (S12) {}}}
child {node[state] (S2) {}
child {node[state] (S21) {}}
child {node[state] (S22) {} edge from parent[light-gray] }};
\end{tikzpicture}
\end{document}
您可以看到以下输出:
问题是,我希望黑线位于灰线之上。这发生在左子树中,因为左边缘在右边缘之前绘制。然而,这并没有发生在右子树中。我希望右子树是左子树的镜像。它应该是这样的:
我尝试改变灰色和黑色节点的顺序并尝试指定子节点的方向,如下所示:
child[right] {node[state] (S22) {} edge from parent[light-gray] }
child[left] {node[state] (S21) {}}};
和这个:
child {node[state, right] (S22) {} edge from parent[light-gray] }
child {node[state, left] (S21) {}}};
但它不起作用!
任何帮助,将不胜感激!
答案1
以下是两个快速解决方法:
代码 A 为路径运算符引入了一个修复程序edge to parent
,该修复程序用作background edge
开关将路径封闭在pgfonlayer
环境中。
代码 B 使用\tikz@swap@growth
来grow'
交换方向。正如您的想法,您也需要交换子代(如果您在一行中有交替的黑/灰线,则此方法不起作用,它们仍然会一个接一个地绘制)。
代码A
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning,automata,backgrounds}
\definecolor{light-gray}{gray}{0.6}
\makeatletter
\def\tikz@@edgetoparent[#1]{%
\let\tikz@edge@to@parent@needed=\pgfutil@empty%
\tikz@node@is@a@labeltrue%
\begingroup
\tikzset{edge from parent,#1}%
\ifpgf@edge@background
\edef\pgf@next{\noexpand\edef\noexpand\pgf@linewidth{\the\pgflinewidth}\noexpand\pgfutil@firstoftwo}
\else
\def\pgf@next{\pgfutil@secondoftwo}
\fi
\pgfmath@smuggleone\pgf@next
\endgroup
\pgf@next{\pgfonlayer{background}\path[style=edge from parent,line width/.expanded=\pgf@linewidth,#1] \tikz@edge@to@parent@path;\endpgfonlayer\tikz@scan@next@command}%
{\tikz@scan@next@command [style=edge from parent,#1] \tikz@edge@to@parent@path}%
}
\newif\ifpgf@edge@background
\tikzset{background edge/.is if=pgf@edge@background}
\makeatother
\begin{document}
\begin{tikzpicture}[line width=.1cm,shorten >=0pt,auto,on grid=false, every state/.style={minimum size=0pt}, level distance=2.0cm, level 1/.style={sibling distance=2cm}, level 2/.style={sibling distance=1cm}, level 3/.style={sibling distance=.5cm}]
\tikzstyle{every node}=[font=\tiny , circle, outer sep=0pt, inner sep=0pt]
\node[] (S) {}
child {node[state] (S1) {}
child {node[state] (S11) {} edge from parent[background edge,light-gray] }
child {node[state] (S12) {}}
}
child {node[state] (S2) {}
child {node[state] (S21) {}}
child {node[state] (S22) {} edge from parent[background edge,light-gray] }
};
\end{tikzpicture}
\end{document}
代码 B
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning,automata}
\definecolor{light-gray}{gray}{0.6}
\makeatletter
\tikzset{swap grow direction/.style={every child/.append code=\tikz@swap@growth}}
\makeatother
\begin{document}
\begin{tikzpicture}[line width=.1cm,shorten >=0pt,auto,on grid=false, every state/.style={minimum size=0pt}, level distance=2.0cm, level 1/.style={sibling distance=2cm}, level 2/.style={sibling distance=1cm}, level 3/.style={sibling distance=.5cm}]
\tikzstyle{every node}=[font=\tiny , circle, outer sep=0pt, inner sep=0pt]
\node[] (S) {}
child {node[state] (S1) {}
child {node[state] (S11) {} edge from parent[light-gray] }
child {node[state] (S12) {}}}
child[swap grow direction] {node[state] (S2) {}
child {node[state] (S22) {} edge from parent[light-gray] }
child {node[state] (S21) {}}};
\end{tikzpicture}
\end{document}
输出
答案2
在我看来,改变 TikZ 路径读取和处理的顺序是徒劳的。因此,快速修复方法是将内容发送到背景层。这需要暂停当前路径,并引入父节点路径(我不确定这一点,一定有更简洁的方法,但我现在想不通)。无论如何,要传递图形参数,您可以在样式键中保留自定义设置的副本,并在需要时应用。
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning,automata,backgrounds}
\definecolor{light-gray}{gray}{0.6}
\begin{document}
\begin{tikzpicture}[
my style/.style={line width=.1cm,shorten >=0pt,auto,on grid=false},
my style,
every state/.style={minimum size=0pt},
level distance=2.0cm,
level 1/.style={sibling distance=2cm},
level 2/.style={sibling distance=1cm},
level 3/.style={sibling distance=.5cm},
every node/.style={font=\tiny , circle, outer sep=0pt, inner sep=0pt},
my edge/.style={edge from parent path={
\pgfextra{%
\begin{pgfonlayer}{background}
\draw[my style,#1] (\tikzparentnode\tikzparentanchor) -- (\tikzchildnode\tikzchildanchor);
\end{pgfonlayer}
}
}
}]
\node[] (S) {}
child {node[state] (S1) {}
child {node[state] (S11) {} edge from parent[light-gray] }
child {node[state] (S12) {}}
child {node[state] (S11) {} edge from parent[my edge=light-gray] }}
child {node[state] (S2) {}
child {node[state] (S21) {}}
child {node[state] (S22) {} edge from parent[my edge=light-gray] }
child {node[state] (23) {}}};
\end{tikzpicture}
\end{document}