箭头TeX
看似垂直居中,高度与 x 字符相同,在本例中为最后一个e
:
\documentclass{article}
\begin{document}
Source $\rightarrow$ Target
\end{document}
TikZ
另一方面,箭头似乎与大写字母高度字符垂直居中,在本例中为大写字母S
和T
:
\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 高度字符结尾,而右侧单词以大写高度字符开头,因此这会产生视觉错觉(至少对我来说是这样),即右侧单词的位置高于左侧单词。我想通过将箭头与TikZ
x 高度字符垂直居中来避免这种情况。我该怎么做?
编辑
事实上我刚刚注意到这不是视觉错觉。右边的单词是放置得更高,因为它包含低于基线的字母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=east
anchor=west
center
从下图(取自 PGFmanual,第 66.2 节预定义形状)中可以看出,由于线条高得惊人,您可以更清楚地看到效果:
所有形状还提供基于实际文本基线的锚点:、 和 以及 、 和text
。base
这base west
使得已经base east
可以使用mid
mid west
mid 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}
(当然,如果边框是draw
n,您将再次获得不同垂直高度的边框,但随后您可以使用text depth
andtext 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 用一个形状连接两个节点(即除coordinate
s 之外的所有节点)时,它会使用节点形状边界上的点。对于线到 ( --
),它会从一个节点的中心“射”到另一个节点的中心。当此射线击中节点的边界时,即设置了线的实际起点。这实际上与角度锚点没有什么不同,因此上面的示例可能只会产生与
\draw [thick, ->] (s.359) -- (t.179);
解决这一切的办法是显而易见的:
\draw [thick, ->] (s.mid east) -- (t.mid west);
但这要求您有选择地选择锚点(可以隐藏在to path
但如果您想涵盖节点位置以及开始和目标的所有可能组合,这也会很快变得复杂)。
那么我们为什么不移动center
锚点呢?
这tikz-cd
提供一个名为的形状asymmetrical rectangle
,它为我们提供了一个center
锚点(和east
和west
),其定义与通常的锚点类似。使用键的值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}