![\hyperlink 与 \hyperref 的不同机制](https://linux22.com/image/417709/%5Chyperlink%20%E4%B8%8E%20%5Chyperref%20%E7%9A%84%E4%B8%8D%E5%90%8C%E6%9C%BA%E5%88%B6.png)
我正在摆弄该hyperref
包以在我的 pdf 中构建超文本结构。乍一看,hyperref
提供了两个类似的宏来在我的文档各部分之间建立链接:\hyperlink{target}{text}
和\hyperref[target]{text}
。您可能会注意到它们的语法略有不同。
我真正感兴趣的是它们不同的工作机制。我将通过以下示例来说明这一点:
\documentclass{article}
\usepackage{pdfpages}
\usepackage[]{hyperref}
\usepackage{mwe}
\begin{document}
\section{Section Heading}
\label{sectionheading}
\includepdf[link=true, linkname=pdfpage]{example-image}
Link to section works with \hyperref[sectionheading]{hyperref}
and with \hyperlink{sectionheading}{hyperlink}
(but with slightly different targets on the page).
Link to pdf works with \hyperlink{pdfpage.1}{hyperlink}
but not with \hyperref[pdfpage.1]{hyperref}
(and not this way, either: \hyperref[pdfpage]{hyperref}).
\end{document}
要链接到label
ed 部分标题,我可以使用这两个命令。虽然\hyperref
将我的 pdf 查看器直接引导到链接的部分,但\hyperlink
将我引导到略有不同的地方,这样我可以看到更多上下文。
\includepdf
但是,要链接到pdfpages
,我只能使用\hyperlink
。\hyperref
根本不起作用。
我怀疑这是因为它们的工作机制存在细微的差异。在检查文件时aux
,我发现一行\newlabel{sectionheading}{{1}{1}{Section Heading}{section.1}{}}
似乎\hyperref
用作目标。但是,我没有找到任何与所包含的 pdf 类似的目标。
我的问题:我想,我非常了解\label
和的工作原理。似乎与增加了可点击性后的工作方式非常相似。您能否向我解释一下它们的工作原理有何不同以及它是如何实现的?例如,哪些机制可以解释单击链接时的差异以及链接目标首先存储在哪里以及如何存储?\ref
\hyperref
\hyperlink
答案1
链接指向目的地。目的地是使用原始\pdfdest
命令在 pdf 中创建的对象(在 pdflatex 中,对于其他引擎,它们是类似的命令)。目的地对象包含一个坐标和一个页面对象参考编号。在 pdf 的不同部分,有一个从目的地名称到此对象的引用。
<<
/D [6 0 R /XYZ 133.768 667.198 null]
>>
hyperref 自动创建许多这样的目的地。
例如,一个\section
命令创建一个名为的目的地section.1
,section.2
等等。
您还可以使用该\hypertarget
命令添加更多目的地。
要创建到此类目的地的链接,您可以直接使用目的地的名称(如果您知道)和\hyperlink
括号参数:
\hyperlink{section.1}{some text}
或者,您可以向 hyperref 内部添加目的地的结构添加一个标签,然后使用\hyperref
括号表示法,然后 hyperref 将通过标签信息找到目的地名称:
\section{section}\label{sectionheading}
\hyperref[sectionheading]{some text}
你的第三个选择不起作用:
\hyperlink{sectionheading}{some text}
它在日志中给出警告:
pdfTeX warning (dest): name{sectionheading} has been referenced but does not
exist, replaced by a fixed one
这意味着您获得了一个链接,但由于目的地sectionheading
不存在,因此链接不是指向正确的位置(用作替换的“固定链接”通常是第一页。)
\includepdf
为名为(在您的示例中)的页面创建多个目的地pdfpage.1
,pdfpage.2
等等。因此,要链接到这些目的地,您必须使用括号表示法:
\hyperlink{pdfpage.1}{hyperlink}
(为了让生活变得更加困难,\hyperref
还接受四个括号内的参数来链接到一个 url,至少我对此经常感到困惑)。
答案2
在你的问题中你说
...
\hyperlink{target}{text}
和\hyperref[target]{text}
...
但应该
...和...\hyperlink{⟨named destination⟩}{⟨text⟩}
\hyperref[⟨cross-referencing-label⟩]{⟨text⟩}
不要将 LaTeX 的交叉引用标签名称与放置在 .pdf 文件中用于超链接的所谓“命名目的地”=“目标”=“锚点”的名称相混淆:
基本上,交叉引用标签是在 LaTeX 运行期间通过 .aux 文件维护的数据记录,并提供包含交叉引用所需信息的数据片段。在 LaTeX 运行期间/在 LaTeX 编译器运行并创建 .pdf 文件/输出文件时存在交叉引用标签。
当 .pdf 文件不存在时/输出文件是在 LaTeX 运行过程中生成的由pdf查看应用程序显示。
交叉引用标签的名称就是记录的名称。通常,这样的记录由几个元素组成,例如页码和某些 LaTeX 节计数器的打印值,以及(如果加载了 hyperref)相应节的标题和放置在 .pdf 文件中的“命名目标”的名称,用于超链接该节/用于在查看 .pdf 文件时“导航”到该节。不同的引用命令可以检索此类记录的不同元素。
例如,\ref
检索 LaTeX 计数器的打印值。如果加载了 hyperref 包,则会检索“命名目标”的名称,该名称由于某些分段命令(\section
、\subsection
、...\caption
等)而自动放置在相应分段项的开头,同时还会检索打印值以将其转换为指向相应分段项的超链接。
我尝试解释与 LaTeX 2ε 交叉引用机制相关的概念我的答案针对这个问题如何防止在新环境中引用枚举?“。
命名目的地 = 目标 = 锚点 -正如 Ulrike Fischer 所解释的那样-- 是一个放置在 .pdf 文件本身中的对象,.pdf 查看应用程序在查看 .pdf 文件时使用它来“导航”到文档的特定“位置”。
当 .pdf 文件/输出文件由 pdf 查看应用程序显示时,命名的目的地/目标/锚点确实存在。
加载 hypperref 包时,LaTeX 在处理诸如\section
、\subsection
、 ... 之类的分段命令时会自动将这些对象/命名目标放入 .pdf 文件中\caption
。由于\label
-命令(触发将要用于交叉引用的数据记录写入 .aux 文件),LaTeX 在其他组件下方还将命名目标的名称作为交叉引用标签的组件存储,该名称由 LaTeX 在遇到\label
相关 -命令之前自动放置为最后一个。引用命令(如\ref
或 )\pageref
可以提取这部分数据以将事物转换为超链接。
除了 hyperref 自动放置命名目的地之外,您还可以\hypertarget
“手动”将命名目的地放入 .pdf 文件中。
\hyperref[sectionheading]{some text}
和 的区别\hyperlink{section.1}{some text}
在于:
可选参数\hyperref[sectionheading]{some text}
表示交叉引用标签并且\hyperref
-command 会将短语“一些文本”包装成超链接,通过从交叉引用标签中获取相应命名目的地的名称,该标签基本上是一份数据记录,其中一个组件表示放入 .pdf 文件中的命名目的地的名称。
第一个非可选参数\hyperlink{section.1}{some text}
直接表示已命名目的地的名称已放入 .pdf 文件中。指定目的地的名称是直接给出的,不能作为交叉引用标签处理的数据记录的组成部分获取。
如果您喜欢繁琐的操作,您可以使用 refcount-package 来获取这些数据记录的单个组件(称为交叉引用标签),然后执行以下操作:
\documentclass{article}
\usepackage{pdfpages}
\usepackage{hyperref}
\usepackage{refcount}
...
\section{section}\label{sectionheading}
...
\IfRefUndefinedBabel{sectionheading}{%
\refused{sectionheading}%
}{%
\hyperlink{\getrefbykeydefault{sectionheading}{anchor}{UndefinedDestination}}%
{some text}%
}
...
使用此构造,在第一次运行 LaTeX 时,即在交叉引用标签尚未记录到 .aux 文件中,因此仍未定义时,将\refused{...}
执行此操作,您会在 .pdf 文件中看到问号,在 .log 文件和控制台中看到警告。
在连续的 LaTeX 运行中,属于交叉引用标签的命名目标的名称sectionheading
将从由交叉引用标签形成的数据记录中提取出来,并通过命令sectionheading
传递给命令。\hyperlink
\getrefbykeydefault
但你实际上并不需要这个。\hyperref[sectionheading]{some text}
更短并且功能相同。;-)