tcolorboxでスライドを作る

:::note info
この記事は <a href="https://adventar.org/calendars/6724">TeX ＆ LaTeX Advent Calendar 2021</a> の22日目の記事です.
21日目は <a href="https://sokrates7chaos.hatenablog.com/entry/2021/12/22/015355">7danmoroboshi さん</a>でした. 23日目は <a href="https://blog.wtsnjp.com/2021/12/23/nlproceedings/">wtsnjp さん</a>です. 
:::

[10日目](https://qiita.com/t_kemmochi/items/0ea192c0eabfdaf09894)にも投稿しているので, ご覧ください.

## 導入: LaTeX でのスライド作成

LaTeX を用いてスライド資料を作る方法はいくつかありますが, 代表的なものは [beamer](https://ctan.org/pkg/beamer) による方法だと思います.
beamer は比較的簡単にきれいなスライドが作成できるうえ, `\pause` コマンド等による段階的な表示 (overlay specification) が容易なため, 使っている人は多いのではと思います. また, ドキュメントが豊富であるのも魅力的です.
一方で, 細かなカスタマイズをしようとするとかなり手間がかかりますし, 使いたいパッケージが使えないケース[^enumitem]もあります. 何より, コンパイルの時間が長すぎます.

[^enumitem]: 例えば, [enumitem パッケージ](https://ctan.org/pkg/enumitem)がうまく動きません. 

overlay specification を使わないのであれば, 「スライドの見た目をしたページ」が出力できればそれで良いはずです.
スライドのような見た目の「箱」であれば, [tcolorbox パッケージ](https://www.ctan.org/pkg/tcolorbox) で出力することができます. 
この「箱」を単体で1ページとして出力できればいいわけですが, それは [preview パッケージ](https://www.ctan.org/pkg/preview) によって実現可能です.
そこで本稿では, **tcolorbox パッケージと preview パッケージを組み合わせてスライドを作る方法**を紹介します.

tcolorbox パッケージの箱は, かなり柔軟にカスタマイズすることができます. 
したがって, スライドの見た目を細かく変えたい人にはうってつけではないかと思います.
一方で, overlay specification を使うことはできません. この点は後述します.

 
## tcolorbox と preview を用いたスライド作成

以下, LuaLaTeX によるコンパイルと日本語の利用を想定して, クラスファイルは `ltjsarticle` としますが, あまり本質的ではないと思います.


### 基本的な構造

以下のような構造のファイルを作っておけば, ひとまず「箱が単体で1ページとして出力された pdf」を作ることができます.

```latex
\documentclass{ltjsarticle}

\usepackage{tcolorbox}
\usepackage[active,tightpage]{preview}
\PreviewEnvironment{minipage}

\begin{document}

    \begin{minipage}{5cm}
        \begin{tcolorbox}[
            adjusted title=スライドタイトル
        ]
            スライドの中身
        \end{tcolorbox}
    \end{minipage}

\end{document}
```

これにより, 以下の出力を得ます.

![20211222_texadvent-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111178/9a4c2999-6b16-3a0a-89fd-72b28ec961a0.png)


上の tex ファイルの中身を簡単に説明します. 

`\usepackage{tcolorbox}` は言うまでもなく, tcolorbox を読み込みます.

`\usepackage[active,tightpage]{preview}` で preview パッケージを読み込みます. 
オプションの `active` はパッケージを有効化するという意味の, `tightpage` は余白を出力しないという意味のオプションです (多分).

`\PreviewEnvironment{minipage}` がミソで, これにより, 「`minipage` 環境の内部だけを独立した1ページとして出力する」ということができるようになります.
なぜかわかりませんが, ここを `\PreviewEnvironment{tcolorbox}` にするとうまくいかなかったので, こうしています.

`\begin{minipage}{5cm}` ～ `\end{minipage}` の中に, スライドの中身を書きます. 
`5cm` という引数でスライドの横幅の長さを指定しています. 今は適当に入力しています.


`minipage` 環境内部の

```tex
\begin{tcolorbox}[
    adjusted title=スライドタイトル
]
    スライドの中身
\end{tcolorbox}
```

の部分が, スライドの本体です. 
今は `adjusted title` というオプションしか書かれていませんが, この部分にさまざまなオプションを記入することで, スライドの見た目を変えることが可能です.

<details><summary>なぜ `title` オプションではなく `adjusted title` なのか</summary>
<div>

`tcolorbox` には `title` というオプションもあり, これを用いても箱のタイトルを設定することができます.
しかしこの場合, タイトルの文字列によってタイトル部分の高さが変わってしまいます.
例えば, `title = Abc` とした箱と `title = Xyz` とした箱では, yの下に伸びる部分の差で, タイトル部分の高さが異なってしまいます. 

一方で, `adjusted title = Abc` と `adjusted title = Xyz` の場合, 同じ高さになります.
実は, `adjusted title` によって高さを設定した場合, タイトルの文字列によらず, `Ägypten` という文字列に合わせた高さになります.

スライドの場合, ページごとにタイトル部分の高さが異なるのは気持ちが悪いので, `adjusted title` を利用していますが, そこを気にしなければ `title` で十分です.

</div>
</details>

なお, 実際に使う場合には, 

```tex 
\renewenvironment{frame}[1]{
    \begin{minipage}{5cm}
        \begin{tcolorbox}[
            adjusted title=#1
        ]
}{
        \end{tcolorbox}
    \end{minipage}
}
```

といった感じで `frame` 環境を定義して使うのが楽であると思いますが, 本稿ではそのような記述はしません.

以下, オプションの記入例を紹介します.

### スライドの大きさの変更

スライドの幅は `minipage` 環境の引数として入力します.
スライドの高さは, `tcolorbox` 環境の `height` オプションで記入します.
つまり, 以下のようにして大きさを指定できます.

```tex:
\begin{minipage}{幅}
    \begin{tcolorbox}[
        adjusted title=スライドタイトル,
        height=高さ
    ]
        スライドの中身
    \end{tcolorbox}
\end{minipage}
```

実際には, 次のように, `\framewidth` という感じで長さをコマンドにするのが楽であると思います.
また, アスペクト比 (4:3なら0.75, 9:16なら0.5625) を予め計算しておいて, 高さは自動で計算するようにしておくと更に楽です.

```tex:プリアンブル
\newlength{\framewidth}
\newlength{\frameheight}
\newcommand{\aspectratio}{0.75} % 16:9 なら 0.5625
\setlength{\framewidth}{12cm}
\setlength{\frameheight}{\aspectratio\framewidth}
```

```tex:document環境内
\begin{minipage}{\framewidth}
    \begin{tcolorbox}[
        adjusted title=スライドタイトル,
        height=\frameheight
    ]
        スライドの中身
    \end{tcolorbox}
\end{minipage}
```

これにより, 以下の出力を得ます.

![20211222_texadvent-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111178/9045d9bc-7207-a943-1aaf-3062497ee315.png)


少しスライドっぽくなりました. 
なお, (本文の) フォントサイズをいじるのではなく, スライドサイズをいじることで, 相対的にフォントサイズを変更する, という仕様です (beamerもそう).
`\framewidth` の値を変えることで, (スライドの/フォントの) 大きさが変わります.


### タイトルのフォントサイズの変更

タイトルのフォントは, `tcolorbox` の `fonttitle` というオプションで変更できます.

```tex
\begin{minipage}{\framewidth}
    \begin{tcolorbox}[
        adjusted title=スライドタイトル,
        height=\frameheight,
        fonttitle=\Large
    ]
        スライドの中身
    \end{tcolorbox}
\end{minipage}
```

![20211222_texadvent-03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111178/844ccbe2-0c33-e70a-5c5a-098a5205e081.png)


フォント (書体) そのものは fontspec パッケージなどを利用して変更すると良いと思います.



### 色の変更

背景とフォントの色は, 以下のオプションにより変更できます.

| オプション | 意味 |
|:----------|:-----|
| `colback` | 中身の背景色 |
| `coltext` | 中身のフォントの色 |
| `colbacktitle` | タイトルの背景色 |
| `coltitle` | タイトルのフォントの色 |

以下に例を記載します (オプションが増えてきたのでコメントをつけました).
わかりやすくするために奇抜な色合いにしています.

```tex 
\begin{minipage}{\framewidth}
    \begin{tcolorbox}[
        % タイトル
        adjusted title=スライドタイトル,
        % 高さ
        height=\frameheight,
        % タイトルのフォント
        fonttitle=\Large,
        % 色
        colback=lime,
        coltext=black,
        colbacktitle=blue,
        coltitle=white
    ]
        スライドの中身
    \end{tcolorbox}
\end{minipage}
```

![20211222_texadvent-04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111178/fe7a5e39-3e0e-2072-8d47-e9d0175e73df.png)

### 枠線の変更

上の図には余計な枠線がついていますね.
これを消して, ついでに角の丸みもなくしましょう.

`boxrule` というオプションで枠線の太さを変更し, `sharp corners` というオプションで角を直角にします.

```tex
\begin{minipage}{\framewidth}
    \begin{tcolorbox}[
        % タイトル
        adjusted title=スライドタイトル,
        % 高さ
        height=\frameheight,
        % タイトルのフォント
        fonttitle=\Large,
        % 色
        colback=white,
        coltext=black,
        colbacktitle=blue,
        coltitle=white,
        % 枠線
        boxrule=0mm,
        sharp corners
    ]
        スライドの中身
    \end{tcolorbox}
\end{minipage}
```


![20211222_texadvent-05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111178/16eebdfe-0905-60f3-762b-ddcca5079e5e.png)


<details><summary>ビューアによっては1ピクセル分の枠線が見えてしまうかもしれません. その場合は...</summary>
<div>

まず, プリアンブルの `\usepackage{tcolorbox}` 以降に `\tcbuselibrary{skins}` と記載します. 

```tex:プリアンブル

\usepackage{tcolorbox}
\tcbuselibrary{skins}
```

その上で, `tcolorbox` のオプションに, `enhanced` と `frame hidden` を追加します.

```tex
\begin{minipage}{\framewidth}
    \begin{tcolorbox}[
        % タイトル
        adjusted title=スライドタイトル,
        % 高さ
        height=\frameheight,
        % タイトルのフォント
        fonttitle=\Large,
        % 色
        colback=white,
        coltext=black,
        colbacktitle=blue,
        coltitle=white,
        % 枠線
        boxrule=0mm,
        sharp corners,
        enhanced,
        frame hidden 
    ]
        スライドの中身
    \end{tcolorbox}
\end{minipage}
```

</div>
</details>


### 余白の変更

余白は, 以下のオプションによって細かく指定できます.

| オプション | 意味 |
|:----------|:-----|
| `boxsep` | 上下左右の余白 |
| `top` | 中身の上部の余白 |
| `bottom` | 中身の下部の余白 |
| `toptitle` | タイトルの上部の余白 |
| `bottomtitle` | タイトルの下部の余白 |
| `left` | 左側の余白 |
| `right` | 右側の余白 |

細かく余白を設定する場合, `boxsep` は `0mm` にしておくと良いと思います.


```tex
\begin{minipage}{\framewidth}
    \begin{tcolorbox}[
        % タイトル
        adjusted title=スライドタイトル,
        % 高さ
        height=\frameheight,
        % タイトルのフォント
        fonttitle=\Large,
        % 色
        colback=white,
        coltext=black,
        colbacktitle=blue,
        coltitle=white,
        % 枠線
        boxrule=0mm,
        sharp corners,
        % 余白
        boxsep=0mm,
        top=1em,
        bottom=1em,
        right=1em,
        left=1em,
        toptitle=1ex,
        bottomtitle=1ex,
    ]
        スライドの中身
    \end{tcolorbox}
\end{minipage}
```

![20211222_texadvent-07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111178/45af02cf-44a4-91a6-1b1d-e53682bedabe.png)


### ページ番号をつける

ちょっと面倒ですが, 「ページ番号を含む TikZ のノードを, tcolorbox の上に描く」という方法を採ります. もっと良い方法があるかもしれません.

まず, プリアンブルに, 以下を追記します:

```tex:プリアンブル
% \usepackage{tcolorbox} 以降に...
\tcbuselibrary{skins}

\usepackage{totalcount}
\newcounter{framenumber}
\setcounter{framenumber}{0}
\DeclareTotalCounter{framenumber}
```

`\tcbuselibrary{skins}` は, 大雑把に言って, tcolorbox の機能を拡張するためのおまじないです.

[totalcount パッケージ](https://ctan.org/pkg/totalcount)は, 総ページ数を記載するために利用します.
`framenumber` というカウンタを定義しておき, `\DeclareTotalCounter{framenumber}` とすることで, `\totalframenumbers` というコマンドで最終的な `framenumber` の値 (総ページ数) を取得することができます.
`framenumber` の値を増やすには, `\refstepcounter{framenumber}` とします.


さて, `tcolorbox` 環境の方は, 以下のようにします.


```tex

\begin{minipage}{\framewidth}
    \begin{tcolorbox}[
        % タイトル
        adjusted title=スライドタイトル,
        % 高さ
        height=\frameheight,
        % タイトルのフォント
        fonttitle=\Large,
        % 色
        colback=white,
        coltext=black,
        colbacktitle=blue,
        coltitle=white,
        % 枠線
        boxrule=0mm,
        sharp corners,
        % 余白
        boxsep=0mm,
        top=1em,
        bottom=1em,
        right=1em,
        left=1em,
        toptitle=1ex,
        bottomtitle=1ex,
        % ページ番号
        enhanced,
        before={\refstepcounter{framenumber}},
        overlay={
            \node[above left,scale=0.7,inner sep=2mm] at (frame.south east) {\color{gray}\theframenumber/\totalframenumbers};
        }
    ]
        スライドの中身
    \end{tcolorbox}
\end{minipage}
```

増えたのは以下の3箇所です.

```tex
enhanced,
before={\refstepcounter{framenumber}},
overlay={
    \node[above left,scale=0.7,inner sep=2mm] at (frame.south east) {\color{gray}\theframenumber/\totalframenumbers};
}
```

- `enhanced` によって, 拡張された機能を使うことができるようになります. 具体的には, `overlay` が使えるようになります.
- `before` は, 箱を描画する前に実行される内容を記述します. ここでは `framenumber` というカウンタの値を増やしています.
- `overlay` の中は `tikzpicture` 環境と同じになっており, ここに TikZ のコマンドを書くことで, `tcolorbox` の上から TikZ の図形が描画されます.

`overlay` の中では, `tcolorbox` 環境そのものを `frame` というノードとして利用できます. つまり, `(frame.south east)` は `tcolorbox` 環境の右下の角です. 
そこに `\node` を置くことで, `\theframenumber/\totalframenumbers`, つまり「ページ番号/総ページ数」を出力します.


1ページ目: 

![20211222_texadvent-08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111178/98babc47-51cb-a210-c249-71637199a0b4.png)

2ページ目:

![20211222_texadvent-09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111178/30705e9e-3e3b-d694-452f-0a095b6899a2.png)

## その他にできること

`tcolorbox` 環境はかなり自由にカスタマイズできるので, 何でもできると言っても過言ではありません.

例えば, プレゼンのタイトル (表紙) ページのデザインや, セクション区切りのページのデザインも, 自由に考えることができます.

他にも, 目次を作ったり, 付録以下は総ページ数に含まないようにするとか, (頑張れば) いろいろできます.

tcolorbox パッケージのより詳しい使い方は, [CTAN](https://ctan.org/pkg/tcolorbox) にある公式ドキュメントが一番参考になります.
また, 日本語での解説記事もたくさん存在しますので, 参考になると思います.

tcolorbox を使って, 自分だけの最強のスライドを作りましょう.


## Q & A


### 上下左右に小さな余白があるのが気になる

上の方法で作った pdf ファイルには, 上下左右に小さな余白があるため, Adobe Acrobat などで全画面表示するとその余白が白く目立ってしまいます.
それが気になる場合, [pagecolor パッケージ](https://ctan.org/pkg/pagecolor)によって pdf の背景色を黒にすることでごまかしましょう. 
プリアンブルに以下を記述すると良いです.

```tex:プリアンブル
\usepackage[pagecolor=black]{pagecolor}
```

pagecolor なし

![20211222_texadvent-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111178/9a4c2999-6b16-3a0a-89fd-72b28ec961a0.png)

pagecolor あり

![20211222_texadvent-10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111178/a6984472-20ce-0415-7dc7-94ddf03b8374.png)


### 箇条書きを beamer のようにカスタマイズしたい

[enumitem パッケージ](https://ctan.org/pkg/enumitem)を使いましょう.


### overlay specification を使いたい

以下の記事を参考に, PowerPoint に変換しちゃいましょう.

https://qiita.com/t_kemmochi/items/0ea192c0eabfdaf09894


### カスタマイズの手間や学習コストはbeamerと大差ないのでは？

それはそう.

### 結局コンパイルに時間がかかるのでは？

それはそう.