tikzcd 能不能智能地放置标签?比如,在绘制下图时,
\begin{tikzcd}[row sep=large]
& C
\arrow[ld, "f"]
\arrow[rd, "g"]
\arrow[d, "!h" , dashed] & \\
A
& A\times B
\arrow[r, "\pi_B"]
\arrow[l, "\pi_A"]
& B
\end{tikzcd}
标签看起来很丑。我必须手动换边,
\begin{tikzcd}[row sep=large]
& C
\arrow[ld, "f", swap]
\arrow[rd, "g"]
\arrow[d, "!h" , dashed] & \\
A
& A\times B
\arrow[r, "\pi_B"]
\arrow[l, "\pi_A", swap]
& B
\end{tikzcd}
有没有更智能的方法来做到这一点?
答案1
标签的放置方式很巧妙,始终位于箭头的左侧。这是蒂克兹 auto
选项安装者TikZ-CD。
不过,它只知道left
和right
,这意味着路径上的节点要么放在路径的左边,要么放在路径的右边。(swap
('
) 钥匙只是检查哪一个是活动的并安装另一个。)
我不喜欢原始代码中的实现方式,但我们能以任何方式扩展它也可以接受
auto = above
节点始终位于路径上方(或垂直线的右侧),并且auto = below
其中节点始终位于路径下方(或垂直线的左侧)。
密钥swap
被重写,以便它也能处理这些新添加的内容。
这仍然是某种愚蠢的智能,因为它永远无法检查它是否看起来不错,或者节点是否位于图表的“外部”。
当然,您可以创建一个自动放置功能,当路径为对角线时将节点置于路径上方,当路径为纯水平路径时将节点置于路径下方,但在我看来,图表越复杂,这些功能就越无用。
例如,在第二个图中,我认为它等同于第一个图,所有节点都应该在另一侧,以便它们位于图的“外侧”,但如果没有外界的巨大帮助(即另一个分析该图的工具),TikZ 将无法弄清楚这一点。
这样,节点至少会一致地放置在路径上方或下方,我认为这会很有帮助。在完成这些图之前,您总是会先看一遍这些图。
代码
\documentclass[tikz,convert]{standalone}
\usetikzlibrary{cd}
\makeatletter
\tikzset{
swap/.style={swap auto/.expand once=\tikz@auto@anchor@direction},
swap auto/.is choice,
/utils/temp/.style args={#1=#2}{
swap auto/#1/.code=\def\tikz@auto@anchor@direction{#2}},
/utils/temp/.list={left=right, right=left, above=below, below=above}
}
\def\tikz@install@auto@anchor@above{%
\let\tikz@do@auto@anchor\tikz@auto@anchor@on
\def\tikz@auto@anchor@direction{above}}
\def\tikz@auto@anchor@above{%
\tikz@auto@pre\tikz@auto@anchor@above@\tikz@auto@post}
\def\tikz@install@auto@anchor@below{%
\let\tikz@do@auto@anchor\tikz@auto@anchor@on
\def\tikz@auto@anchor@direction{below}}
\def\tikz@auto@anchor@below{%
\tikz@auto@pre\tikz@auto@anchor@below@\tikz@auto@post}
\def\tikz@auto@anchor@above@{%
\def\tikz@anchor{south}%
\ifdim\pgf@x>0.05pt
\ifdim\pgf@y>0.05pt
\def\tikz@anchor{south east}%
\else\ifdim\pgf@y<-0.05pt
\def\tikz@anchor{south west}%
\fi\fi
\else\ifdim\pgf@x<-0.05pt
\ifdim\pgf@y>0.05pt
\def\tikz@anchor{south east}%
\else\ifdim\pgf@y<-0.05pt
\def\tikz@anchor{south east}%
\fi\fi
\else
\ifdim\pgf@y>0pt
\def\tikz@anchor{east}%
\else
\def\tikz@anchor{west}%
\fi
\fi\fi
}
\def\tikz@auto@anchor@below@{%
\def\tikz@anchor{north}%
\ifdim\pgf@x>0.05pt
\ifdim\pgf@y>0.05pt
\def\tikz@anchor{north west}%
\else\ifdim\pgf@y<-0.05pt
\def\tikz@anchor{north east}%
\fi\fi
\else\ifdim\pgf@x<-0.05pt
\ifdim\pgf@y>0.05pt
\def\tikz@anchor{north east}%
\else\ifdim\pgf@y<-0.05pt
\def\tikz@anchor{north west}%
\fi\fi
\else
\ifdim\pgf@y>0pt
\def\tikz@anchor{west}%
\else
\def\tikz@anchor{east}%
\fi
\fi\fi}
\makeatother
\begin{document}
\begin{tikzcd}[row sep=large, auto=above]
& C \arrow[ld, "f"]
\arrow[rd, "g"]
\arrow[d, "!h" , dashed] \\
A
& A \times B \arrow[r, "\pi_B"']
\arrow[l, "\pi_A"']
& B
\end{tikzcd}
\begin{tikzcd}[row sep=large, auto=below]
A
& A \times B \arrow[r, "\pi_B"']
\arrow[l, "\pi_A"']
& B \\
& C \arrow[lu, "f"]
\arrow[ru, "g"]
\arrow[u, "!h"', dashed]
\end{tikzcd}
\end{document}