将 tikz 箭头与 x 高度字符对齐

将 tikz 箭头与 x 高度字符对齐

箭头TeX看似垂直居中,高度与 x 字符相同,在本例中为最后一个e

\documentclass{article}
\begin{document}
Source $\rightarrow$ Target
\end{document}

在此处输入图片描述

TikZ另一方面,箭头似乎与大写字母高度字符垂直居中,在本例中为大写字母ST

\documentclass{article}
\usepackage{tikz}
\begin{document}

\begin{tikzpicture}
    \draw [thick, ->] (0,0) -- (1,0);
    \node[left] at (0,0) {Source};
    \node[right] at (1,0) {Target};
\end{tikzpicture}

\end{document} 

在此处输入图片描述

由于左侧单词以 x 高度字符结尾,而右侧单词以大写高度字符开头,因此这会产生视觉错觉(至少对我来说是这样),即右侧单词的位置高于左侧单词。我想通过将箭头与TikZx 高度字符垂直居中来避免这种情况。我该怎么做?


编辑

事实上我刚刚注意到这不是视觉错觉。右边的单词放置得更高,因为它包含低于基线的字母g。为了立即避免此问题(我想这应该是一个单独的问题),请考虑以下示例。箭头相对于前一个不居中e,这对我来说看起来不对:

在此处输入图片描述

答案1

TikZ 使用水平框来输入节点内容。如果没有指定明确的文本深度,则下降部分将导致节点高度发生变化。因此,当您的文本有下降部分和无下降部分时,它们的高度必然会有所不同。就是这样。没有什么奇怪的,也没有什么可改变的。

您曾经提到,如果没有下降部,为什么需要文本深度,这再次是为了确保任何有/无下降部的节点是否正确对齐,而无需真正解析每个字母并检查是否有任何字母。

但!

如果您不打算在节点周围绘制任何边框,那么您可以重置文本深度并使用它。

\documentclass[tikz,border=5mm]{standalone}
\begin{document}
\begin{tikzpicture}[every node/.style={inner sep=0,text depth=0,draw}]
    \node[anchor=east] (s) at (0,0) {Source};
    \node[anchor=west] (t) at (1,0) {Target};
\draw[->] (s) -- (t);
\end{tikzpicture}
\end{document}

在此处输入图片描述

或者,如果您不介意多花点力气来绘制连接,那么您可以将节点与基线对齐,并让下行部分尊重基线。但是,这样节点就不会在水平方向上完美对齐,您需要使用正交标识符来绘制连接。

\documentclass[tikz,border=5mm]{standalone}
\begin{document}
\begin{tikzpicture}[every node/.style={draw,inner sep=0}]
    \node[anchor=mid] (s) at (0,0) {Source};
    \node[anchor=mid] (t) at (1.5,0) {Target};
\draw[->,ultra thick] (s) -- (t);
\draw[-latex,red] (s) -- (t.west|-s);
\end{tikzpicture}
\end{document}

在此处输入图片描述

请记住,如果您想同时使用left和,则需要做一些准备mid。据我所知,它目前还不支持。

答案2

跟进敲击回答,我们可以使用 来text depth = 0指示框的底部绘制方式好像没有带下降部分的字符,并使用 来text height = 1ex绘制框的顶部好像所有字符都是 x 高度:

\documentclass[tikz, border = 1mm]{standalone}
\begin{document}
\begin{tikzpicture}[every node/.style = {inner sep = 0, text height = 1ex, text depth = 0, draw}]
    \node[anchor = east] (s) at (0,0) {Sphinx};
    \node[anchor = west] (t) at (1,0) {Sphinx};
    \draw[->] (s) -- (t);
\end{tikzpicture}
\end{document}

在此处输入图片描述

结果是箭头与 x 高度字符的中心垂直对齐。

答案3

TikZ/PGF 如何将文本放置在节点内?

对于具有一个部分的简单节点(我将使用形状rectangle作为此示例),TikZ 将所有节点内容放在一个 TeX 框中(像往常一样具有宽度,高度和深度),并使用填充/pgf/inner xsep和在其周围构建一条路径/pgf/inner ysep

节点的中心将是 TeX 框的中心。对于具有不同高度和深度的框,此中心将不会在各个框的垂直高度(相对于基线)上处于同一水平。

TikZ 如何放置节点?

在您的示例中,您使用了left和,它们与和right基本相同。这些锚点位于与锚点相同的垂直高度(根据定义)上,并且位于节点的相应边界上。anchor=eastanchor=westcenter

从下图(取自 PGFmanual,第 66.2 节预定义形状)中可以看出,由于线条高得惊人,您可以更清楚地看到效果:
在此处输入图片描述

所有形状还提供基于实际文本基线的锚点:、 和 以及 、 和textbasebase west使得已经base east可以使用midmid westmid east

\documentclass[tikz]{standalone}
\begin{document}
\begin{tikzpicture}
  \draw [thick, ->] (0,0) -- node[at start, anchor=mid east] {Source}
                             node[at end,   anchor=mid west] {Target} (1,0);
\end{tikzpicture}
\end{document} 

(当然,如果边框是drawn,您将再次获得不同垂直高度的边框,但随后您可以使用text depthandtext height和/或\strut(等于text depth=+.3\baselineskip, text height=+.7\baselineskip。)

中锚的一个愚蠢问题

中间锚点位于基线(及其锚点)上方 0.5ex。但要小心!尽管这是一个依赖于字体大小的长度单位,但 TikZ 实现它有点愚蠢。观察当你添加[nodes={font=\Huge}]tikzpicture上面示例的环境时会发生什么:
在此处输入图片描述

使用[nodes={/utils/exec=\Huge}](或者\Huge在 开始后立即使用tikzpicture) 您将获得预期的输出。

TikZ 如何在节点之间绘制路径?

中间锚点看起来是个好的解决方案,对吧?

即使你以某种方式定位节点,使它们的基线(或它们的“中线”)位于相同的垂直高度,连接仍然

\documentclass[tikz]{standalone}
\usetikzlibrary{positioning}
\begin{document}
\begin{tikzpicture}
  \node (s) {Source}; \node (t) [mid right=of s] {Target};
  \draw [thick, ->] (s) -- (t);
\end{tikzpicture}
\end{document} 

不会被我们的愿望所吸引。

当您要求 TikZ 用一个形状连接两个节点(即除coordinates 之外的所有节点)时,它会使用节点形状边界上的点。对于线到 ( --),它会从一个节点的中心“射”到另一个节点的中心。当此射线击中节点的边界时,即设置了线的实际起点。这实际上与角度锚点没有什么不同,因此上面的示例可能只会产生与

\draw [thick, ->] (s.359) -- (t.179);

解决这一切的办法是显而易见的:

\draw [thick, ->] (s.mid east) -- (t.mid west);

但这要求您有选择地选择锚点(可以隐藏在to path但如果您想涵盖节点位置以及开始和目标的所有可能组合,这也会很快变得复杂)。

那么我们为什么不移动center锚点呢?

tikz-cd提供一个名为的形状asymmetrical rectangle,它为我们提供了一个center锚点(和eastwest),其定义与通常的锚点类似。使用键的值mid而不是固定值。不幸的是,这与中间锚点一样,在字体大小方面存在同样的问题。.5ex/tikz/commutative diagrams/center yshift

在此处输入图片描述

代码

\documentclass[tikz]{standalone}
\usepackage{tikz-cd}\tikzset{nodes={shape=asymmetrical rectangle}}
\usetikzlibrary{positioning}
\begin{document}
\begin{tikzpicture}
  \draw [thick, ->] (0,0) -- node[at start, left] {Source}
                             node[at end,  right] {Target} (1,0);
\end{tikzpicture}
\begin{tikzpicture}
  \node (s) {Source}; \node (t) [right=of s] {Target};
  \draw [thick, ->] (s) -- (t);
\end{tikzpicture}
\end{document} 

相关内容