我正在尝试实现命令(让我们命名它fn
),旨在像overset
命令一样工作,并用一些曲线在下划线下划线。使用 TikZ 执行此操作。下部单词被设为节点文本,上部单词被设为节点的标签选项。因此,出现了一些额外的填充,如下面的 MWE 中所示。
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{xparse}
\newcommand{\tmpText}{}
\NewDocumentCommand{\fn}{ > { \SplitArgument { 1 } { : } } m }{%
{%
\NewDocumentCommand{\tmpSubject}{mm}{%
\IfValueT{##2}{\renewcommand{\tmpText}{##2}}
\tikz[baseline=(Root.base)]{%
\node[inner sep=0pt,
outer sep=0pt,
label={[yshift=-2,
font=\tiny\itshape] \tmpText}] (Root) {##1};
\draw[line width=0.75]
let
\p1 = (Root.south west),
\p2 = (Root.south east)
in
(\x1, \y1 - 2) -- (\x2, \y2 - 2);
}%
}%
\tmpSubject#1%
}%
}
\begin{document}
{\setlength{\fboxsep}{0pt}
\fbox{\fn{Hello:world}}
\fbox{\fn{Hello}}
\fbox{Hello}
}
\end{document}
因此,主要问题是可以修正填充,以便输出如下所示(颜色仅用于指示所需区域)?当然,如果上方文本比下方文本宽,宽度也应该更正为较宽的文本。唉,我自己在论坛和 TikZ 上都找不到答案。
还有一个问题从性能角度来看,在另一个命令中定义临时命令是一种好方法吗?就像我fn
在 MWE 中定义的那样?我使用这种嵌套宏的主要动机不是在主文档中定义我不直接需要的函数。
提前致谢。
答案1
您正确地将inner sep
节点的 设置为 0,但忘记将标签(也是一个节点)设置为 0。一旦您将其设置为 0(或0.5pt
光学元件),就不再需要负yshift
。我还添加了%
,并用 标记了位置<-
。
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{xparse}
\newcommand{\tmpText}{}
\NewDocumentCommand{\fn}{ > { \SplitArgument { 1 } { : } } m }{%
{%
\NewDocumentCommand{\tmpSubject}{mm}{%
\IfValueT{##2}{\renewcommand{\tmpText}{##2}}% <-
\tikz[baseline=(Root.base)]{%
\node[inner sep=0pt,
outer sep=0pt,
label={[inner sep=0.5pt,
font=\tiny\itshape] \tmpText}] (Root) {##1};
\draw[line width=0.75]
let
\p1 = (Root.south west),
\p2 = (Root.south east)
in
(\x1, \y1 - 2) -- (\x2, \y2 - 2);
}%
}%
\tmpSubject#1%
}%
}
\begin{document}
{\setlength{\fboxsep}{0pt}
\fbox{\fn{Hello:world}}
\fbox{\fn{Hello}}
\fbox{Hello}
}
\end{document}
或者没有calc
但有line cap=rect
。
\documentclass{article}
\usepackage{tikz}
\usepackage{xparse}
\newcommand{\tmpText}{}
\NewDocumentCommand{\fn}{ > { \SplitArgument { 1 } { : } } m }{%
{%
\NewDocumentCommand{\tmpSubject}{mm}{%
\IfValueT{##2}{\renewcommand{\tmpText}{##2}}%
\tikz[baseline=(Root.base)]{%
\node[inner sep=0pt,
outer sep=0pt,
label={[inner sep=0.5pt,
font=\tiny\itshape] \tmpText}] (Root) {##1};
\draw[line width=0.75,line cap=rect]
([yshift=-2pt]Root.south west)--
([yshift=-2pt]Root.south east);
}%
}%
\tmpSubject#1%
}%
}
\begin{document}
{\setlength{\fboxsep}{0pt}
\fbox{\fn{Hello:world}}
\fbox{\fn{Hello}}
\fbox{Hello}
}
\end{document}
或者,第三个版本我们不允许 Ti钾Z 根据具有 的路径选择边界框line cap=rect
。为此,我只在底部插入一个坐标并绘制线overlay
,即将其排除在边界框之外。此版本附带与普通\fbox
es 的比较。
\documentclass{article}
\usepackage{tikz}
\usepackage{xparse}
\newcommand{\tmpText}{}
\NewDocumentCommand{\fn}{ > { \SplitArgument { 1 } { : } } m }{%
{%
\NewDocumentCommand{\tmpSubject}{mm}{%
\IfValueT{##2}{\renewcommand{\tmpText}{##2}}%
\tikz[baseline=(Root.base)]{%
\node[inner sep=0pt,
outer sep=0pt,
label={[inner sep=0.5pt,
font=\tiny\itshape] \tmpText}] (Root) {##1};
\path ([yshift=-2.375pt]Root.south west);
\draw[line width=0.75,overlay]
([yshift=-2pt]Root.south west)--
([yshift=-2pt]Root.south east);
}%
}%
\tmpSubject#1%
}%
}
\newcommand{\cmd}[1]{\texttt{\textbackslash #1}}
\begin{document}
{\setlength{\fboxsep}{0pt}
\begin{tabular}{|@{\,}l@{\,}|c|@{}l@{}|}
\fbox{\fn{Hello:world}} & \cmd{fd} with label & \fbox{\fn{Hello:world}}\\
\fbox{Hello} & just \cmd{fbox} for comparison & \fbox{Hello}\\
\fbox{\fn{Hello}} & \cmd{fd} without label & \fbox{\fn{Hello}} \\
\fbox{Hello} & just \cmd{fbox} for comparison & \fbox{Hello}\\
\end{tabular}}
\end{document}
我还请您注意一下tikzmark
命令附带的库,\tikzmarknode
它可以检测其环境文本(数学模式与文本模式等),这可能在这里有用。