使用 TikZ 旋转文本中的单个字母

使用 TikZ 旋转文本中的单个字母

我想旋转 TikZ 边缘标签文本中的每个字符,同时保持边缘标签的方向不变。

以下代码:

\documentclass{standalone}

\usepackage{tikz}

% TikZ styles
\tikzset{
root/.style={circle,draw=red!70,fill=red!30},
leaf/.style={circle,draw=blue!70,fill=blue!30},
label/.style={sloped,above}
}

\begin{document}
\begin{tikzpicture}
\node [root] {$r$}
    child { node [leaf] {$l_1$}
        edge from parent
        node[label] {\texttt{CBA}}
    }
    child { node [leaf] {$l_2$}
        edge from parent
        node[label] {\texttt{ABC}}
    };
\end{tikzpicture}
\end{document}

产生这个:

字符未旋转

文本根据边缘方向倾斜,这很好。但是,我想要实现的是保持文本基线倾斜,同时单独旋转每个字符。如果需要,我还想调整字符间距。

我想要实现的效果是让每个字符看起来好像根本没有旋转,同时改变整个文本的方向。结果应该是这样的:

字符旋转

有什么方法可以实现吗?我知道我可以沿着边缘的路径放置一些包含单个字母的节点,但我想知道是否有更简单的方法。

理想情况下,我更喜欢拥有某种风格,比如说slopedandrotated,它可以做到这一点。

答案1

可以稍微改变装饰以使单个字符直立。此解决方案需要使用和text along path进行一些手动调整才能正确定位,但效果很好。它支持原始装饰的所有选项,如手册中所述。要使用文本格式选项,您必须将它们括在分隔符中,默认为。我添加了一个选项来增加单个字母之间的间距,称为,因为某些字体选项在默认间距下看起来不太好。raisetext align/left indenttext along path|kern factor

\documentclass[border=5mm]{standalone}

\usepackage{tikz}
\usetikzlibrary{decorations.text}

% TikZ styles
\tikzset{
root/.style={circle,draw=red!70,fill=red!30},
leaf/.style={circle,draw=blue!70,fill=blue!30},
label/.style={sloped,above}
}

\makeatletter
\tikzset{
    /pgf/decoration/kern factor/.code=\pgfmathsetmacro\tikz@textalongpath@kern{0.5*#1},
    /pgf/decoration/kern factor=1
}
\pgfdeclaredecoration{text along path not sloped}{initial}{
\state{initial}[width=+0pt, next state=left indent, 
    persistent precomputation={%
        \edef\pgf@lib@dec@text@indent@left{\pgfkeysvalueof{/pgf/decoration/text align/left indent}}%
        \edef\pgf@lib@dec@text@indent@right{\pgfkeysvalueof{/pgf/decoration/text align/right indent}}%
        \edef\pgf@lib@dec@text@align{\pgfkeysvalueof{/pgf/decoration/text align/align}}%
        \pgfdecoratedremainingdistance=\pgfdecoratedpathlength%
      \advance\pgfdecoratedremainingdistance by-\pgf@lib@dec@text@indent@right\relax%
      \edef\pgfdecoratedpathlength{\the\pgfdecoratedremainingdistance}%
      \pgf@lib@dec@text@getwidth%
      \pgf@x=\pgf@lib@dec@text@width\relax%
      \pgf@y=\pgfdecoratedremainingdistance%
      \ifpgf@lib@dec@text@fit%
        \advance\pgf@y by-\pgf@lib@dec@text@indent@left\relax%
        \advance\pgf@y by-\pgf@x%
        \ifpgf@lib@dec@text@stretch@spaces%
            \def\pgf@lib@dec@text@character@shift{0pt}%
            \divide\pgf@y by\pgf@lib@dec@space@count\relax%
            \edef\pgf@lib@dec@text@space@shift{\the\pgf@y}%
        \else%
            \c@pgf@counta=\pgf@lib@dec@character@count\relax%
            \advance\c@pgf@counta by-1\relax%
            \divide\pgf@y by\c@pgf@counta\relax%
            \edef\pgf@lib@dec@text@character@shift{\the\pgf@y}%
            \def\pgf@lib@dec@text@space@shift{0pt}%
          \fi%
          \ifdim\pgf@y<0pt\relax%
            \pgf@lib@dec@text@fitfalse%
            \pgf@lib@dec@text@stretch@spacesfalse%
            \def\pgf@lib@dec@text@character@shift{0pt}%
            \def\pgf@lib@dec@text@space@shift{0pt}%
          \fi%
      \else%
        \def\pgf@lib@dec@text@character@shift{0pt}%
        \def\pgf@lib@dec@text@space@shift{0pt}%
          \ifx\pgf@lib@dec@text@align\pgf@lib@dec@text@left@text%
          \else%
            \ifx\pgf@lib@dec@text@align\pgf@lib@dec@text@right@text%
                \advance\pgf@y by-\pgf@x%
                \edef\pgf@lib@dec@text@indent@left{\the\pgf@y}%
            \else%
                \advance\pgf@y by-\pgf@x%
                \advance\pgf@y by-\pgf@lib@dec@text@indent@left\relax%
                \pgf@y=0.5\pgf@y%
                \advance\pgf@y by\pgf@lib@dec@text@indent@left\relax%
                \edef\pgf@lib@dec@text@indent@left{\the\pgf@y}%
            \fi%
          \fi%
      \fi%
      \let\pgfdecorationrestoftext=\pgfdecorationtext%
    }]{}
\state{left indent}[width=+\pgf@lib@dec@text@indent@left, next state=scan]{}
%
\state{scan}[width=+0pt, next state=before typeset,
 persistent precomputation={
   \pgf@lib@dec@text@scanchar%
   \ifvoid\pgf@lib@dec@text@box%
     \setbox\pgf@lib@dec@text@box\hbox{}%
     \wd\pgf@lib@dec@text@box16383pt\relax%
   \fi%
 }]{}
%
\state{before typeset}[width=+\tikz@textalongpath@kern\wd\pgf@lib@dec@text@box, next state=typeset]{}
%
\state{typeset}[width=+0pt, next state=after typeset]
{%
  \pgftransformresetnontranslations
  \setbox\pgf@hbox\hbox{\copy\pgf@lib@dec@text@box}%
  \pgfqboxsynced\pgf@hbox%
}
\state{after typeset}[width=+.5\wd\pgf@lib@dec@text@box, next state=shift,
    persistent precomputation={%
    \ifpgf@lib@dec@text@fit%
        \ifpgf@lib@dec@text@stretch@spaces%
            \ifpgf@lib@dec@text@scan@space%
                \let\pgf@lib@dec@text@shift=\pgf@lib@dec@text@space@shift%
            \else%
                \def\pgf@lib@dec@text@shift{0pt}%
            \fi%
        \else%
            \let\pgf@lib@dec@text@shift=\pgf@lib@dec@text@character@shift%
          \fi%
        \else%
            \def\pgf@lib@dec@text@shift{0pt}%
      \fi%  
  }]{}
\state{shift}[width=+\pgf@lib@dec@text@shift, next state=scan]{}
\state{final}{}
}
\makeatother

\begin{document}
\begin{tikzpicture}
\node [root] {$r$}
    child { node [leaf] {$l_1$}
        edge from parent[postaction={
            decorate,
            decoration={
                text along path not sloped,
                raise=-1.75ex,
                text={|\ttfamily|CBA},
                text align/left indent=0.5em,
                kern factor=2
            }
        }]
    }
    child { node [leaf] {$l_2$}
        edge from parent [postaction={
            decorate,
            decoration={
                text along path not sloped,
                raise=0.4ex,
                text={|\ttfamily|ABC},
                text align/left indent=0.3em,
                kern factor=2
            }
        }]
    };
\end{tikzpicture}
\end{document}

相关内容