Выровнять стрелку tikz с символом x-height

Выровнять стрелку tikz с символом x-height

Стрелка 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-height, а слово справа начинается с символа cap-height, это создает оптическую иллюзию (по крайней мере для меня), что слово справа расположено выше, чем слово слева. Я бы хотел избежать этого, отцентрировав стрелку TikZвертикально с помощью символа x-height. Как это сделать?


РЕДАКТИРОВАТЬ

На самом деле я только что заметил, что это не оптическая иллюзия. Слово справаявляетсяразмещен выше, потому что содержит букву 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

Продолжениеударные'sотвечать, мы можем использовать 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-height.

решение3

Как TikZ/PGF размещает текст внутри узла?

Для простых узлов (а я буду использовать фигуру rectangleдля этого примера) с одной частью TikZ помещает все содержимое узла в один блок TeX (с шириной, высотой и глубиной, как обычно) и создает вокруг него путь с отступами /pgf/inner xsepи /pgf/inner ysep.

Центр узла будет центром TeX-бокса. С боксами разной высоты и глубины он не будет на той же вертикальной высоте (относительно базовой линии) по всем боксам.

Как TikZ размещает узлы?

В вашем примере вы используете leftи, rightчто по сути то же самое, что anchor=eastи anchor=westсоответственно. Эти якоря лежат на той же вертикальной высоте, что и centerякорь (по определению), и на соответствующей границе узла.

Как вы можете видеть на следующем изображении (взято из руководства PGF, раздел 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} 

(Конечно, если border равен drawn, вы снова получите border на разной вертикальной высоте, но тогда вы можете использовать text depthand text 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якорь?

Thetikz-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} 

Связанный контент