10 如何将beamer目录放置在指定位置?

发布于 2025-08-23 18:16:02
  1. 在位置方面,我希望目录能够被放置在cyan色的框框里。red框左边界往左,准备布置一些装饰物,因此视觉上的可用版面是red框左边界到red框右边界(tips:默认情况下beamer页边距为1厘米),因此将目录放在red框的中心是个不错的选择。
  2. 在对齐方面,我希望目录能够悬挂缩进,突出序号。(已实现)
  3. 在大小方面,我希望cyan框的大小能够根据目录的实际内容自动变化。这样的话,就可以兼顾这个目录整体上的位置居于red框中心和序号后悬挂对齐。

image.png

我自己进行了一个尝试。我将元素section in toc的模板fancytoc的内容改写为一个tblr环境,如果这样行得通的话,那真的能在大体上实现需求,但是,这样会得到一个不允许在 LR mode 中使用的错误。


群友Eureka提出以下方法论。我看不懂,只感到震撼……所谓内部的那个这个盒子堆盒子这些东西,额,它们到底指代什么呢?看得我一头雾水,感觉讳莫如深。而且l3coffin是编程层面的东西,超出我的能力边界了……

把 tableofcontents 内部的那个 input 命令,放到这个盒子里面,然后就没啥技术含量了,直接堆盒子就行了(觉得堆盒子太复杂了,可以直接用 l3coffin 模块)

我又尝试了另一种方法,就是把\tableofcontents放到一个tcolorbox环境里面。在tcolorbox里面,可以轻而易举地实现序号后悬挂对齐。并且,借助changlepage包临时改变左侧边距,这样就可以实现版心与red框完全吻合,这样就实现了外部位置的一个粗略改变。然后就是考虑tcolorbox的整体尺寸问题,但是目前还没有一个比较好的方法。虽然tcolorbox提供了hbox键,但\tableofcontents似乎无法装在一个hbox里(稍后再测试一次)。因为,通常情况下,tcolorbox的整体宽度是默认的,但是可以手工指定(已确认存在这样的接口)。想实现依靠内容自动计算整体尺寸,感觉仍然需要一个很复杂的计算。


最小工作示例:

\documentclass[aspectratio=169]{beamer}
%%------------------------------------
%%------------------------------------
\usepackage{varwidth}
\defbeamertemplate{section in toc}{fancytoc}{%
    \leavevmode\leftskip=4mm%
    \llap{\hbox to 4mm{\inserttocsectionnumber.\hfil}}%
    \begin{varwidth}[t]{20em}\inserttocsection\end{varwidth}\par%
}
\setbeamertemplate{section in toc}[fancytoc]
%%------------------------------------
%%------------------------------------
\usepackage{tikz}
\usetikzlibrary{calc}
\NewDocumentCommand{\drawmwehelplines}{}{%
    \tikz[remember picture,overlay]{
        \draw ([shift={(1cm,-1cm)}]current page.north west) -| 
              ([shift={(-1cm,1cm)}]current page.south east) -| 
              ([shift={(1cm,-1cm)}]current page.north west) -- cycle;
        \coordinate (toccenter) at ($([shift={(2.8cm,1cm)}]current page.south west)!.5!([shift={(-1cm,-1cm)}]current page.north east)$);
        \fill [red] 
              (toccenter) circle (2pt);
        \draw [cyan]
              ($(-2cm,-1.5cm)+(toccenter)$) rectangle 
              ($(2cm,1.5cm)+(toccenter)$);
        \draw [dashed,red,very thick]
              ($(-6.1cm,-3.5cm)+(toccenter)$) rectangle
              ($(6.1cm,3.5cm)+(toccenter)$);
    }%
}
%%------------------------------------
%%------------------------------------
\begin{document}

\frame{
    \drawmwehelplines
    \contentsname
    \tableofcontents
}

\section{section section section section section section section section section section one}
\frame{\frametitle{section one}some text}

\section{section two}
\frame{\frametitle{section two}some text}

\end{document}

查看更多

关注者
1
被浏览
302
M
M 2025-08-24
这家伙很懒,什么也没写!

coffins其实不难的,如果你对l3coffins编程式的书写风格感到不适,可以试试xcoffins--这就是一个把l3coffins封装好的,对用户使用相对友好的包。
回到这个问题上来,使用coffins来解决的思路大概如下:

  1. 把整个页面划分成3个部分,左边装饰+右边背景(红色虚线)+目录,对应三个coffins,这里假设左右比例为1:4

    \NewCoffin\LeftCoffin
    \NewCoffin\RightCoffin
    \NewCoffin\TocCoffin
    
    \SetVerticalCoffin \LeftCoffin {0.2\linewidth}{\color{red!20!white}\rule{\linewidth}{8cm}}
    \SetVerticalCoffin \RightCoffin {0.8\linewidth}{\color{blue!20!white}\rule{\linewidth}{8cm}}
  2. 在每个section开始的时候计数并设置label

    \newcounter{totalsection}
    \regtotcounter{totalsection}
    
    \AddToHook{cmd/section/before}{\refstepcounter{totalsection}}
    \AtBeginSection[]{\label{sec:\thesection}}
  3. 目录中section的标题可以通过 2. 中设置的label来获取,这样的好处就是可以通过现有的工具(如enumitem,tikz等)灵活地给目录设置样式,而beamer自带的defbeamertemplate操作比较复杂,扩展性也一般。

    \newsavebox{\myenum}
    \newlength{\enumwidth}
    
    \begin{lrbox}{\myenum}
        \begin{varwidth}{20em}
            \begin{enumerate}[label={\arabic*.\,},left=0pt]
                \foreach \i in {1,...,\number\totvalue{totalsection}} {
                    \item \hyperlink{sec:\i}{\nameref{sec:\i}}
                }
            \end{enumerate}
        \end{varwidth}
    \end{lrbox}
    \settowidth{\enumwidth}{\usebox{\myenum}}
    
    \SetVerticalCoffin \LeftCoffin {0.2\linewidth}{\color{red!20!white}\rule{\linewidth}{8cm}}
    \SetVerticalCoffin \RightCoffin {0.8\linewidth}{\color{blue!20!white}\rule{\linewidth}{8cm}}
    \SetVerticalCoffin \TocCoffin {\enumwidth}{\color{red}\fbox{\usebox{\myenum}}}
  4. 设置好这些盒子后,就可以通过盒子自带的锚点(需要的时候也可以自定义锚点),按照特定的布局进行拼接

        \SetHorizontalCoffin \OutputCoffin{}
        \JoinCoffins \RightCoffin[hc,vc]\TocCoffin[hc,vc]
        \JoinCoffins \OutputCoffin[l,vc]\LeftCoffin[l,vc]
        \JoinCoffins \OutputCoffin[r,vc]\RightCoffin[l,vc]
        \TypesetCoffin \OutputCoffin

完整代码如下

\documentclass[aspectratio=169]{beamer}
%%------------------------------------
%%------------------------------------
\usepackage{pgffor}
\usepackage{totcount}
\usepackage{xcoffins}
\usepackage{varwidth}
\usepackage{enumitem}

\NewCoffin\LeftCoffin
\NewCoffin\RightCoffin
\NewCoffin\TocCoffin
\NewCoffin\OutputCoffin

\newcounter{totalsection}
\regtotcounter{totalsection}

\AddToHook{cmd/section/before}{\refstepcounter{totalsection}}
\AtBeginSection[]{\label{sec:\thesection}}

\newsavebox{\myenum}
\newlength{\enumwidth}

\newcommand{\makecoffins}{
    \begin{lrbox}{\myenum}
        \begin{varwidth}{20em}
            \begin{enumerate}[label={\arabic*.\,},left=0pt]
                \foreach \i in {1,...,\number\totvalue{totalsection}} {
                    \item \hyperlink{sec:\i}{\nameref{sec:\i}}
                }
            \end{enumerate}
        \end{varwidth}
    \end{lrbox}
    \settowidth{\enumwidth}{\usebox{\myenum}}
    
    \SetVerticalCoffin \LeftCoffin {0.2\linewidth}{\color{red!20!white}\rule{\linewidth}{8cm}}
    \SetVerticalCoffin \RightCoffin {0.8\linewidth}{\color{blue!20!white}\rule{\linewidth}{8cm}}
    \SetVerticalCoffin \TocCoffin {\enumwidth}{\color{red}\fbox{\usebox{\myenum}}}

    \SetHorizontalCoffin \OutputCoffin{}
    \JoinCoffins \RightCoffin[hc,vc]\TocCoffin[hc,vc]
    \JoinCoffins \OutputCoffin[l,vc]\LeftCoffin[l,vc]
    \JoinCoffins \OutputCoffin[r,vc]\RightCoffin[l,vc]
    \TypesetCoffin \OutputCoffin
}

\begin{document}

\frame{
    \makecoffins
    %\tableofcontents
}

%\section{section one}
\section{section section section section section section section section section section one}
\frame{\frametitle{section one}some text}

\section{section two}
\frame{\frametitle{section two}some text}

\end{document}

局部截取_20250824_154944.png

局部截取_20250824_155319.png

1 个回答

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友

手机
浏览

扫码手机浏览