Hyperref \pageref 链接指向第一页

Hyperref \pageref 链接指向第一页

在回答这个问题我遇到了 hyperref 的一个不寻常的功能。

问题是,有时 hyperref 生成的超链接会\pageref指向文档的第一页,而不是它们应该指向的页面。以下是 MWE:

\documentclass{article}
\usepackage[colorlinks]{hyperref}
\begin{document}
Page 1\newpage
Page 2\label{page2}\newpage
Page 3: Here is a link to \pageref{page2}
\end{document}

单击第 3 页上的链接会将您带回到第 1 页而不是第 2 页,即使 pdf 文件显示链接在第 2 页。根据记录,我注意到页码是阿拉伯语(罗马字母会导致问题)并且我使用的是 TeXLive 2014 和 pdflatex。

现在这个具体问题是已知显然这不是一个错误,因为标签不会创建,anchor所以没有任何内容可以链接。事实上,如果我将我的最小工作示例更改为:

\documentclass{article}
\usepackage[colorlinks]{hyperref}
\begin{document}
Page 1\newpage
\newcounter{acounter}\refstepcounter{acounter}
Page 2\label{page2}\newpage
Page 3: Here is a link to \pageref{page2}
\end{document}

第 3 页上的链接现在正确地将我送回第 2 页。

有趣的是,如果我改写

\documentclass{article}
\usepackage[colorlinks]{hyperref}
\begin{document}
\newcounter{acounter}\refstepcounter{acounter}
Page 1\newpage
Page 2\label{page2}\newpage
Page 3: Here is a link to \pageref{page2}
\end{document}

然后我的超链接又错了,因为它把我带回了第 1 页。可以说,由于当前页面上没有锚点,hyperref 混淆是合理的。另一方面,由于 latex 确实正确地生成了正确的页码,我认为 hpyerref 在所有这些情况下都应该生成正确的超链接。

所以我的问题是:什么应该在这些情况下 hyperref 会做什么?

从上面的链接来看,这些可能不是错误……就我个人而言,我想知道为什么\label不创建超链接锚点。

答案1

hyperref将其超链接指向最后一个锚点,此锚点通过宏设置\refstepcounter。实际上,hyperref重新定义传统的\refstepcounter以插入适当的锚点(\hyper@refstepcounter参见hyperref.dtx)。

超级链接。下面是一个突出动机的展示:

\documentclass{article}
\usepackage{hyperref}
\newcommand{\hlabel}{\phantomsection\label}
\begin{document}

\section{A section}\label{sec:hyp1}

See section~\ref{sec:hyp1}.

\section{Another section}\hlabel{sec:hyp2}

See section~\ref{sec:hyp2}.

\end{document}

在上述示例中,\hlabel我们特意插入了一个锚点(从而忽略了其他锚点的设置),以符合您的要求。此锚点使用 进行设置\phantomsection

单击链接sec:hyp1会跳转回实际的章节标题。嘿,太棒了!单击会sec:hyp2跳转至章节标题下方。但这并不好,因为您不知道跳转的是哪个章节。当然,这个讨论可能看起来微不足道,而且取决于您的 PDF 缩放级别,但我希望这一点已经说清楚了。

因此,锚点的位置与 的位置是分开的\label。如果需要,它允许您自行判断超链接的目标。但是,一般来说,超链接通常应该跳转到计数器被踩到的位置。

另外,带有\captions 的浮点数的可预测性(就其结构而言)正是该包的原因hypcap诞生了。也就是说,通过点击与标题/浮动计数器步进关联的超链接,您可以跳转到浮动实际开始的位置。

答案2

让我们看看它\label的工作原理。 的目的\label是在文件中写入注释,.aux以便以后使用\ref或进行检索\pageref。该命令使用立即地的当前值\@currentlabel以及发货时的当前页码。

的值\@currentlabel由命令(本地)设置为计数器值的当前表示;当然,也可以手动设置。这就是为什么命令应该跟在后面的\refstepcounter原因,例如:它是步进相关计数器。\label\caption\caption

注释hyperref更加复杂。在经典设置中,代码如下

\section{A title}\label{x}

写类似

\newlabel{x}{{1}{1}}

第二个参数是一对{<counter representation>}{<page number>}。使用hyperref相同的代码可以写

\newlabel{x}{{1}{1}{A title}{section.1}{}}

第二个参数是一个 5 元组:计数器表示、页码、标题或说明(如果计数器指的是标题或说明)和超文本锚点。第五组保留用于其他目的。锚点也由设置\refstepcounter,因为它必须指向后续超链接应指向的位置。

可以清楚地看到,设置锚点是不可能的\label,因为没有办法知道这个锚点应该指向哪里:计数器已经踏出,将设置锚点的工作交给它\label会导致错误的点。

如果您尝试设置\label远离计数器步进的位置,您将看到第二个参数的第一部分仍然\newlabel包含“旧”信息,正是同一组级别的\@currentlabel(以及使用的其他类似宏)中包含的信息。hyperref

对于\label仅用于\pageref一个的,必须手动设置锚点:

\phantomsection\label{y}

会写出如下注释

\newlabel{y}{{1}{8}{abc}{section*.1}{}}

其中锚点名称以唯一方式分配。当然,计数器表示(第二个参数中的第一个项\newlabel)将包含不应依赖的“随机”信息。

为什么\pagelabel不存在命令?很简单:当 LaTeX 发布时,甚至还没有想到超文本。您可以定义自己的命令:

\newcommand{\pagelabel}[1]{\phantomsection\label{#1}}

相关内容