我自己进行了一个尝试。我将元素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}
coffins
其实不难的,如果你对l3coffins
编程式的书写风格感到不适,可以试试xcoffins
--这就是一个把l3coffins
封装好的,对用户使用相对友好的包。
回到这个问题上来,使用coffins
来解决的思路大概如下:
把整个页面划分成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}}
在每个section
开始的时候计数并设置label
\newcounter{totalsection}
\regtotcounter{totalsection}
\AddToHook{cmd/section/before}{\refstepcounter{totalsection}}
\AtBeginSection[]{\label{sec:\thesection}}
目录中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}}}
设置好这些盒子后,就可以通过盒子自带的锚点(需要的时候也可以自定义锚点),按照特定的布局进行拼接
\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}
居然还有这么好用的包!它极大地降低了排版设计的难度,并且完美实现了我的需求!感谢!
但是,实际上,我并不需要额外的背景颜色,因此我将
的相关部分改为了:
还有其他的方式,设置一个透明的占位盒子吗?
考虑到
左右盒子
的使用,回答中使用了enumerate
环境来排版目录,我想似乎我的第一个尝试(用tblr
环境来排版目录)可以稍加修改而成功实现?晚些时候再测试一次。@u101077
\color{red!20!white}\rule{\linewidth}{8cm}
只是为了方便观察目录位置,所以临时填充了一个符合尺寸需求的带颜色的“实心线条”作为内容来撑开盒子。其他实现透明占位盒效果的参考:
直接把
color
改成white
建一个宽度与
coffin
相同的盒子,里面用宽度为0
,高度为h
的线条撑开@u23703
\color{<color>}
提供的白色是透明的?@u101077 并不是透明的,只是和默认的页面底色同为白色,看不出来而已。毕竟这个盒子存在的意义就是可以避免手动计算中心点,工具盒的命~