Стрелка 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 равен draw
n, вы снова получите border на разной вертикальной высоте, но тогда вы можете использовать text depth
and 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 соединить два узла с помощью формы (т. е. все, кроме coordinate
s), он использует точки на границе форм узлов. Для линии-к ( --
) он «стреляет» из центра одного узла в центр другого узла. Там, где этот луч касается границы узла, устанавливается фактическое начало линии. Это на самом деле ничем не отличается от угловых якорей, поэтому пример выше может просто дать тот же результат, что и
\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}