![Метки Tikz смещаются в зависимости от размера букв](https://rvso.com/image/281567/%D0%9C%D0%B5%D1%82%D0%BA%D0%B8%20Tikz%20%D1%81%D0%BC%D0%B5%D1%89%D0%B0%D1%8E%D1%82%D1%81%D1%8F%20%D0%B2%20%D0%B7%D0%B0%D0%B2%D0%B8%D1%81%D0%B8%D0%BC%D0%BE%D1%81%D1%82%D0%B8%20%D0%BE%D1%82%20%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80%D0%B0%20%D0%B1%D1%83%D0%BA%D0%B2.png)
Общее описание внутреннего поведения
Метки на рисунке tikz смещены (например, на ) точно к краю букв в метках, т.е. она занимает нижний выносной элемент (см.Статья Википедии о спусковом механизме) букв во внимание, как у буквы «г» (или «п» в слове «Сфинкс»).
Другой аспект (почему этот вопрос)
Но тогда следующие примеры уже не выглядят симметричными.
\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\coordinate (leadl) at (1,0);
\coordinate (leadr) at (2,0);
\fill (leadl) circle[radius=2pt];
\fill (leadr) circle[radius=2pt];
\node[above] at (leadl) {left};
\node[above] at (leadr) {right};
\end{tikzpicture}
\end{document}
\documentclass[tikz]{standalone}
\begin{document}
\begin{tikzpicture}
\coordinate (leadl) at (1,0);
\coordinate (leadr) at (2,0);
\fill (leadl) circle[radius=2pt];
\fill (leadr) circle[radius=2pt];
\node[below] at (leadl) {lelele};
\node[below] at (leadr) {rerere};
\end{tikzpicture}
\end{document}
Проблема, требующая решения
Какой самый простой способ обойти эту (в некоторых случаях желаемую) особенность? Я не хочу анализировать каждый символ во всех метках узлов, которые я печатаю.
решение1
TikZ уже понимает эту проблему и предлагает text depth
длину. Вы можете либо обнулить ее, либо добавить фиксированную глубину ко всем узлам. Пример (мне почему-то нравится тесный дизайн)
\documentclass[tikz]{standalone}
\begin{document}
\begin{tikzpicture}[scale=1.5]
\coordinate (leadl) at (3,0);
\coordinate (leadr) at (5,0);
\fill (leadr) circle[radius=2pt];
\fill (leadl) circle[radius=2pt];
\node[above] at (leadl) {left circle};
\node[above,text depth=0pt] at (leadr) {right circle};
\end{tikzpicture}
\end{document}
решение2
Вот общее решение с двумя вариантами: \strut
или \vphantom
. Это решение можно использовать с многострочными узлами или разными размерами шрифта.
\documentclass{standalone}
\usepackage{tikz}
\tikzset{
fix node via strut/.style={
execute at begin node={\strut},
execute at end node={\strut},
},
fix node via vphantom/.style={
execute at begin node={\vphantom{Ag}},
execute at end node={\vphantom{Ag}},
},
}
\begin{document}
\begin{tikzpicture}
\coordinate (leadl) at (1,0);
\coordinate (leadr) at (2,0);
\fill (leadl) circle[radius=2pt];
\fill (leadr) circle[radius=2pt];
\node[fix node via strut,above,align=center] at (leadl) {left\\left};
\node[fix node via strut,above,align=center] at (leadr) {right\\right};
\node[fix node via strut,below,font=\large] at (leadl) {lelele};
\node[fix node via strut,below,font=\large] at (leadr) {rerere};
\node[blue,above] at (current bounding box.north){via strut};
\end{tikzpicture}
\begin{tikzpicture}
\coordinate (leadl) at (1,0);
\coordinate (leadr) at (2,0);
\fill (leadl) circle[radius=2pt];
\fill (leadr) circle[radius=2pt];
\node[fix node via vphantom,above,align=center] at (leadl) {left\\left};
\node[fix node via vphantom,above,align=center] at (leadr) {right\\right};
\node[fix node via vphantom,below,font=\large] at (leadl) {lelele};
\node[fix node via vphantom,below,font=\large] at (leadr) {rerere};
\node[red,above] at (current bounding box.north){via vphantom};
\end{tikzpicture}
\end{document}
решение3
Что вам нужно сделать, так это добавить anchor=base
к опциям двух узлов. Это выровняет две метки по их базовым линиям. Вероятно, вы хотели написать:
\node[above of=leadl, anchor=base] {left circle};
Чтобы прикрепиться к подъему или спуску, используйте eg anchor=north
. Это прикрепит узел к середине верхнего края узла. Однако внутри узла есть некоторая невидимая отбивка (попробуйте добавить eg , fill=blue
чтобы увидеть отбивку). Чтобы удалить отбивку, используйте inner sep=0pt
. Другие варианты для позиции привязки включают north east
, north west
, south east
и т. д.
решение4
Я написал что-то вроде этого для похожей цели. Возможно, это немного громоздко для того, что оно делает, но, возможно, вы найдете это полезным.
\usepackage{xparse}
\makeatletter
\newcommand{\standardisebox}[1]{%
\smash{#1}\vphantom{\strpeters@box@determining@symbol}%
}
\let\standardizebox\standardisebox
\NewDocumentCommand{\setboxdeterminingsymbol}{sm}{%
\IfBooleanTF {#1}%
{\gdef\strpeters@box@determining@symbol{#2}}%
{\def\strpeters@box@determining@symbol{#2}}%
}
\NewDocumentCommand{\resetboxdeterminingsymbol}{s}{%
\IfBooleanTF {#1}%
{\setboxdeterminingsymbol*{0}}%
{\setboxdeterminingsymbol{0}}%
}
\resetboxdeterminingsymbol
\makeatother
Это работает так: вы оборачиваете текст узла, \standardisebox
и он набирается так, как будто имеет высоту и глубину цифры 0 вместо его истинной высоты и глубины. Вы можете изменить символ, используемый для определения высоты и глубины, с помощью макроса \setboxdeterminingsymbol
и сбросить его до обычного с помощью \resetboxdeterminingsymbol
. Используйте звездчатые формы для глобальных изменений.
\documentclass{standalone}
\usepackage{tikz}
\usepackage{xparse}
\makeatletter
\newcommand{\standardisebox}[1]{%
\smash{#1}\vphantom{\strpeters@box@determining@symbol}%
}
\let\standardizebox\standardisebox
\NewDocumentCommand{\setboxdeterminingsymbol}{sm}{%
\IfBooleanTF {#1}%
{\gdef\strpeters@box@determining@symbol{#2}}%
{\def\strpeters@box@determining@symbol{#2}}%
}
\NewDocumentCommand{\resetboxdeterminingsymbol}{s}{%
\IfBooleanTF {#1}%
{\setboxdeterminingsymbol*{0}}%
{\setboxdeterminingsymbol{0}}%
}
\resetboxdeterminingsymbol
\makeatother
\begin{document}
\begin{tikzpicture}
\coordinate (leadl) at (1,0);
\coordinate (leadr) at (2,0);
\fill (leadr) circle[radius=2pt];
\fill (leadl) circle[radius=2pt];
\node[above] at (leadl) {\standardisebox{left}};
\node[above] at (leadr) {\standardisebox{right}};
\end{tikzpicture}
\end{document}
В моем случае я размещал узлы (фактически метки узлов) систематически внутри другого макроса, поэтому использование макроса для сброса всех их полей не было сложной работой. Если вы устанавливаете много узлов вручную, то обертывание каждого из них в макрос может оказаться трудным.