Uma TeX
seta é aparentemente centrada verticalmente com a altura de um caractere x, neste caso o final e
:
\documentclass{article}
\begin{document}
Source $\rightarrow$ Target
\end{document}
Uma TikZ
seta, por outro lado, parece estar centralizada verticalmente com um caractere de altura máxima, neste caso a maiúscula S
e 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}
Como a palavra à esquerda termina com um caractere de altura x e a palavra à direita começa com um caractere de altura máxima, isso cria a ilusão de ótica (pelo menos para mim) de que a palavra à direita está colocada mais acima do que o palavra à esquerda. Gostaria de evitar isso centralizando a TikZ
seta verticalmente com um caractere de altura x. Como posso fazer isso?
EDITAR
Na verdade, acabei de notar que isso não é uma ilusão de ótica. A palavra à direitaécolocado mais alto porque contém a letra g
que fica abaixo da linha de base. Para evitar esse problema agora (acho que deveria ser uma questão separada), considere o exemplo a seguir. A seta não está centralizada em relação à anterior e
e isso me parece errado:
Responder1
TikZ usa hboxes para digitar o conteúdo do nó. Se não houver profundidade de texto explícita especificada, os descendentes farão com que a altura do nó mude. Então quando você tiver um texto com descendentes e não descendentes a altura deles será necessariamente diferente. É sobre isso. Não há surpresa e também não há muito o que mudar.
Você mencionou por que precisaria de uma profundidade de texto se não tiver um descendente e isso é novamente para garantir que qualquer nó sem/sem descendentes se alinhe corretamente, sem realmente analisar cada letra e verificar se há alguma.
Mas!
Se você não for desenhar nenhuma borda ao redor dos nós, poderá redefinir a profundidade do texto e conviver com ela.
\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}
Ou, alternativamente, se você não se importar em desenhar a conexão com um pouco mais de trabalho, poderá alinhar os nós em relação à sua linha de base com os descendentes respeitando-a. No entanto, os nós não estarão perfeitamente alinhados horizontalmente e você precisará desenhar as conexões com, digamos, identificadores orto.
\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}
Tenha em mente que você precisa fazer alguma preparação se quiser usar ambos left
e mid
. Não é suportado imediatamente, tanto quanto eu sei.
Responder2
Acompanhandopercussãoderesponder, podemos usar text depth = 0
para indicar que a parte inferior da caixa é desenhada como se não houvesse caracteres com descendentes, e usar text height = 1ex
para desenhar a parte superior da caixa como se todos os caracteres tivessem altura 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}
O resultado é que a seta fica alinhada verticalmente com o centro dos caracteres de altura x.
Responder3
Como o TikZ/PGF coloca texto dentro de um nó?
Para nós simples (e usarei a rectangle
forma para este exemplo) com uma parte o TikZ coloca todo o conteúdo do nó em uma caixa TeX (com largura, altura e profundidade como de costume) e constrói um caminho ao redor dele com o preenchimento /pgf/inner xsep
e /pgf/inner ysep
.
O centro do nó será o centro da caixa TeX. Com caixas com alturas e profundidades diferentes, isso não estará na mesma altura vertical (em relação à linha de base) entre as caixas.
Como o TikZ coloca nós?
No seu exemplo, você usa left
e right
que é basicamente o mesmo que anchor=east
e anchor=west
respectivamente. Estas âncoras ficam na mesma altura vertical da center
âncora (por definição) e na respectiva borda do nó.
Como você pode ver na imagem a seguir (retirada do PGFmanual, seção 66.2 Formas Predefinidas) você pode ver os efeitos muito mais claros graças a uma linha alta ridícula:
Todas as formas também fornecem âncoras baseadas na linha de base do texto real: text
, base
, base west
e base east
bem como mid
, mid west
e mid east
. Isso já torna possível usar
\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}
(É claro que, se a borda for draw
n, você obterá bordas em diferentes alturas verticais novamente, mas poderá usar text depth
e text height
e/ou \strut
(que é igual a text depth=+.3\baselineskip, text height=+.7\baselineskip
.)
Um problema bobo com âncoras intermediárias
As âncoras intermediárias ficam 0,5ex acima da linha de base (e suas âncoras). Mas cuidado! Mesmo que esta seja uma unidade de comprimento dependente do tamanho da fonte, o TikZ a implementa de forma um pouco boba. Observe o que acontece quando você adiciona [nodes={font=\Huge}]
ao tikzpicture
ambiente do exemplo acima:
Com [nodes={/utils/exec=\Huge}]
(ou apenas usando \Huge
após o início do tikzpicture
) você obtém uma saída que esperava.
Como o TikZ desenha um caminho entre os nós?
As âncoras intermediárias parecem uma boa solução, certo?
Mesmo se você posicionar os nós de forma que suas linhas de base (ou suas "linhas médias") fiquem posicionadas na mesma altura vertical, a conexão como em
\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}
não será atraído pelos nossos desejos.
Quando você pede ao TikZ para conectar dois nós com uma forma (ou seja, todos menos coordinate
s), ele usa pontos na borda das formas dos nós. Para um line-to ( --
) ele "dispara" do centro de um nó para o centro do outro nó. Onde este raio atinge a borda do nó, o início real da linha é definido. Na verdade, isso não é nada diferente das âncoras angulares, então o exemplo acima pode resultar no mesmo que
\draw [thick, ->] (s.359) -- (t.179);
A solução para tudo isso é óbvia:
\draw [thick, ->] (s.mid east) -- (t.mid west);
Mas isso exige que você escolha seletivamente as âncoras (que podem estar ocultas em um to path
mas que também se tornará complexo rapidamente se você quiser cobrir todas as combinações possíveis de posicionamento de nós, bem como inícios e alvos).
Por que não movemos a center
âncora então?
Otikz-cd
fornece uma forma chamada asymmetrical rectangle
que nos dá uma center
âncora (e east
e west
) que é semelhante à definida como as mid
âncoras usuais. Em vez de um valor fixo, .5ex
o valor da /tikz/commutative diagrams/center yshift
chave é usado. Infelizmente, isso apresenta o mesmo problema em relação ao tamanho da fonte que as âncoras intermediárias.
Código
\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}