將 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 高度字元結尾,而右側的單字以大寫高度字元開頭,因此這會產生視覺錯覺(至少對我而言),即右側的單字位置高於右側的單字。我想透過將TikZ箭頭與 x 高度字元垂直居中來避免這種情況。我怎樣才能做到這一點?


編輯

事實上我只是注意到這不是視錯覺。右邊這個詞g放置得更高,因為它包含低於基線的字母。為了立即避免這個問題(我想這應該是一個單獨的問題),請考慮以下範例。箭頭沒有相對於前面的居中e,這在我看來是錯誤的:

在此輸入影像描述

答案1

TikZ 使用 hboxes 來輸入節點內容。如果沒有指定明確的文字深度,下降部分將導致節點高度變化。因此,當您的文字帶有下降部分和無下降部分時,它們的高度必然會有所不同。就是這樣。沒有什麼意外,也沒有太大的改變。

您已經提到,如果沒有下降部分,為什麼需要文字深度,這又是為了確保任何沒有下降部分的節點是否正確對齊,而無需真正解析每個字母並檢查是否有任何字母。

但!

如果您不打算在節點周圍繪製任何邊框,那麼您可以重置文字深度並接受它。

\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 框中(與往常一樣具有寬度、高度和深度),並使用 padding/pgf/inner xsep和建立圍繞它的路徑/pgf/inner ysep

節點的中心將是 TeX 框的中心。對於具有不同高度和深度的盒子,盒子之間的垂直高度(相對於基線)不會相同。

TikZ 如何放置節點?

在您的範例中,您使用的left和分別與和right基本相同。這些錨點與錨點位於相同的垂直高度(根據定義),並且位於節點的相應邊界上。anchor=eastanchor=westcenter

如下圖所示(取自 PGF 手冊第 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 depthtext 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 用形狀(即 s 之外的所有節點)連接兩個節點時,coordinate它會使用節點形狀邊界上的點。對於 line-to ( --),它從一個節點的中心「射」到另一個節點的中心。當這條射線撞擊節點的邊界時,線的實際起點被設定。事實上,這與角度錨點沒有什麼不同,因此上面的範例可能會導致與

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

所有這一切的解決方案是顯而易見的:

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

但這需要您有選擇地選擇錨點(可以隱藏在 a 中,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} 

相關內容