reveal.js を 使って、Markdown で プレゼンテーション・スライド が 作れる ようになりました.
Markdown で 書くので デザインや多様な表現はできないことは承知しているのですが、右下にあるコントロール・ボタンでデザインが気になります. というこうとで、公式のオンライン・デモのコントロール・ボタンっぽくしてみたいと思います.
※ 以降「公式のオンライン・デモ」を「公式デモ」と表記します (ソースに demo.html
があるので、ここまではオンラインをつけてましたが長いので
作業環境
- Windows 10 64bit
- reveal.js 3.5.0
デザインの違い と 作りたいものの確認
現在の状況について確認します.
まずは、自分で作成したスライドです. 右下のコントロール・ボタンは [ ▶ ] の ような形です.
続いて、公式デモのスライドです. 右下のコントロール・ボタンは [ > ] の ような形です.
この [ ▶ ]を、公式デモの [ > ] に したいというものになります.
あとは、最初のスライドと、下のスライドがある際に、コントロール・ボタンが少し動きます. スライドに動きがあると気になってしまうというのもありますが、ナビゲーションの観点から動いてもいいのかなぁと思います.
今回は、以下の3つを作ります
- 右下のコントロール・ボタンを [ > ] の デザインにする
- 最初のスライドはコントロール・ボタンがわずかに動く
- 下のスライドがある場合は、コントロール・ボタン の [ V ] と [ > ] を わずかに動く
公式デモ の デザイン を 持ってくる
コントロール・ボタンのデザインについて、実は公式デモと配布版では CSS が 異なっています.
特に CONTROLS 以下は完全に違う状態で、これがデザインの [ ▶ ] と [ > ] の 違いになっています.
ということで、公式デモの CONTROLS
部分 の CSS を、自分のスライドの HTML <link>
タグの下へ コピーします.1
<style>
2
.reveal .controls {
3
display: none;
4
position: absolute;
5
top: auto;
6
bottom: 12px;
7
right: 12px;
8
left: auto;
9
z-index: 1;
10
color: #000;
11
pointer-events: none;
12
font-size: 10px; }
13
.reveal .controls button {
14
position: absolute;
15
padding: 0;
16
background-color: transparent;
17
border: 0;
18
outline: 0;
19
cursor: pointer;
20
color: currentColor;
21
-webkit-transform: scale(0.9999);
22
transform: scale(0.9999);
23
transition: color 0.2s ease, opacity 0.2s ease, -webkit-transform 0.2s ease;
24
transition: color 0.2s ease, opacity 0.2s ease, transform 0.2s ease;
25
z-index: 2;
26
pointer-events: auto;
27
font-size: inherit;
28
visibility: hidden;
29
opacity: 0;
30
-webkit-appearance: none;
31
-webkit-tap-highlight-color: transparent; }
32
.reveal .controls .controls-arrow:before,
33
.reveal .controls .controls-arrow:after {
34
content: '';
35
position: absolute;
36
top: 0;
37
left: 0;
38
width: 2.6em;
39
height: 0.5em;
40
border-radius: 0.25em;
41
background-color: currentColor;
42
transition: all 0.15s ease, background-color 0.8s ease;
43
-webkit-transform-origin: 0.2em 50%;
44
transform-origin: 0.2em 50%;
45
will-change: transform; }
46
.reveal .controls .controls-arrow {
47
position: relative;
48
width: 3.6em;
49
height: 3.6em; }
50
.reveal .controls .controls-arrow:before {
51
-webkit-transform: translateX(0.5em) translateY(1.55em) rotate(45deg);
52
transform: translateX(0.5em) translateY(1.55em) rotate(45deg); }
53
.reveal .controls .controls-arrow:after {
54
-webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-45deg);
55
transform: translateX(0.5em) translateY(1.55em) rotate(-45deg); }
56
.reveal .controls .controls-arrow:hover:before {
57
-webkit-transform: translateX(0.5em) translateY(1.55em) rotate(40deg);
58
transform: translateX(0.5em) translateY(1.55em) rotate(40deg); }
59
.reveal .controls .controls-arrow:hover:after {
60
-webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-40deg);
61
transform: translateX(0.5em) translateY(1.55em) rotate(-40deg); }
62
.reveal .controls .controls-arrow:active:before {
63
-webkit-transform: translateX(0.5em) translateY(1.55em) rotate(36deg);
64
transform: translateX(0.5em) translateY(1.55em) rotate(36deg); }
65
.reveal .controls .controls-arrow:active:after {
66
-webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-36deg);
67
transform: translateX(0.5em) translateY(1.55em) rotate(-36deg); }
68
.reveal .controls .navigate-left {
69
right: 6.4em;
70
bottom: 3.2em;
71
-webkit-transform: translateX(-10px);
72
transform: translateX(-10px); }
73
.reveal .controls .navigate-right {
74
right: 0;
75
bottom: 3.2em;
76
-webkit-transform: translateX(10px);
77
transform: translateX(10px); }
78
.reveal .controls .navigate-right .controls-arrow {
79
-webkit-transform: rotate(180deg);
80
transform: rotate(180deg); }
81
.reveal .controls .navigate-right.highlight {
82
-webkit-animation: bounce-right 2s 50 both ease-out;
83
animation: bounce-right 2s 50 both ease-out; }
84
.reveal .controls .navigate-up {
85
right: 3.2em;
86
bottom: 6.4em;
87
-webkit-transform: translateY(-10px);
88
transform: translateY(-10px); }
89
.reveal .controls .navigate-up .controls-arrow {
90
-webkit-transform: rotate(90deg);
91
transform: rotate(90deg); }
92
.reveal .controls .navigate-down {
93
right: 3.2em;
94
bottom: 0;
95
-webkit-transform: translateY(10px);
96
transform: translateY(10px); }
97
.reveal .controls .navigate-down .controls-arrow {
98
-webkit-transform: rotate(-90deg);
99
transform: rotate(-90deg); }
100
.reveal .controls .navigate-down.highlight {
101
-webkit-animation: bounce-down 2s 50 both ease-out;
102
animation: bounce-down 2s 50 both ease-out; }
103
.reveal .controls[data-controls-back-arrows="faded"] .navigate-left.enabled,
104
.reveal .controls[data-controls-back-arrows="faded"] .navigate-up.enabled {
105
opacity: 0.3; }
106
.reveal .controls[data-controls-back-arrows="faded"] .navigate-left.enabled:hover,
107
.reveal .controls[data-controls-back-arrows="faded"] .navigate-up.enabled:hover {
108
opacity: 1; }
109
.reveal .controls[data-controls-back-arrows="hidden"] .navigate-left.enabled,
110
.reveal .controls[data-controls-back-arrows="hidden"] .navigate-up.enabled {
111
opacity: 0;
112
visibility: hidden; }
113
.reveal .controls .enabled {
114
visibility: visible;
115
opacity: 0.9;
116
cursor: pointer;
117
-webkit-transform: none;
118
transform: none; }
119
.reveal .controls .enabled.fragmented {
120
opacity: 0.5; }
121
.reveal .controls .enabled:hover,
122
.reveal .controls .enabled.fragmented:hover {
123
opacity: 1; }
124
125
.reveal:not(.has-vertical-slides) .controls .navigate-left {
126
bottom: 1.4em;
127
right: 6.4em; }
128
129
.reveal:not(.has-vertical-slides) .controls .navigate-right {
130
bottom: 1.4em;
131
right: 1.4em; }
132
133
.reveal:not(.has-horizontal-slides) .controls .navigate-up {
134
right: 1.4em;
135
bottom: 6.4em; }
136
137
.reveal:not(.has-horizontal-slides) .controls .navigate-down {
138
right: 1.4em;
139
bottom: 1.4em; }
140
141
.reveal.has-dark-background .controls {
142
color: #fff; }
143
144
.reveal.has-light-background .controls {
145
color: #000; }
146
147
.reveal.no-hover .controls .controls-arrow:hover:before,
148
.reveal.no-hover .controls .controls-arrow:active:before {
149
-webkit-transform: translateX(0.5em) translateY(1.55em) rotate(45deg);
150
transform: translateX(0.5em) translateY(1.55em) rotate(45deg); }
151
152
.reveal.no-hover .controls .controls-arrow:hover:after,
153
.reveal.no-hover .controls .controls-arrow:active:after {
154
-webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-45deg);
155
transform: translateX(0.5em) translateY(1.55em) rotate(-45deg); }
156
157
@media screen and (min-width: 500px) {
158
.reveal .controls[data-controls-layout="edges"] {
159
top: 0;
160
right: 0;
161
bottom: 0;
162
left: 0; }
163
.reveal .controls[data-controls-layout="edges"] .navigate-left,
164
.reveal .controls[data-controls-layout="edges"] .navigate-right,
165
.reveal .controls[data-controls-layout="edges"] .navigate-up,
166
.reveal .controls[data-controls-layout="edges"] .navigate-down {
167
bottom: auto;
168
right: auto; }
169
.reveal .controls[data-controls-layout="edges"] .navigate-left {
170
top: 50%;
171
left: 8px; }
172
.reveal .controls[data-controls-layout="edges"] .navigate-right {
173
top: 50%;
174
right: 8px; }
175
.reveal .controls[data-controls-layout="edges"] .navigate-up {
176
top: 8px;
177
left: 50%; }
178
.reveal .controls[data-controls-layout="edges"] .navigate-down {
179
bottom: 8px;
180
left: 50%; } }
181
</style>
スタイルを適用する要素を追加する
CSS を 持ってきただけでは、コントロール・ボタンは変化しません.
実は(実はが多い…)、コピーしたスタイル controls-arrow
を 適用するためのタグが必要です. これも公式デモと JavaScript が 異なっている点になります.
さすがに reveal.js
本体を変更したくないですし、CDN からとってこれないのも困ります.
なのでイベント・フックを使って HTML が 生成された後に、必要となる要素を追加するようにしました.
以下のコードを HTML の <script>
タグ にある、 Reveal.initialize({});
の 下に追加します.1
<script>
2
Reveal.addEventListener('ready', (event) => {
3
document.querySelector('aside.controls').dataset.controlsBackArrows = 'faded';
4
Array.from(document.querySelectorAll('aside.controls > button'), e => {
5
let child = document.createElement('div');
6
child.setAttribute('class', 'controls-arrow');
7
e.appendChild(child);
8
e.style.color = 'rgb(66, 175, 250)';
9
});
10
});
11
</script>
reveal.js で コンテンツの準備ができた ready
イベントで、以下の処理をしています.
querySelector('aside.controls')
で、コントロール・ボタンを保持しているコンテナの要素取得します.
データセット controlsBackArrows
に faded
を 設定し、戻るボタン(左と上) に ボタンが薄くなるようなエフェクトをつけます.
querySelectorAll('aside.controls > button')
で、すべてのコントロール・ボタンを取得します.
各ボタンの子要素に <div class="controls-arrow"></div>
タグをを追加、このタグが先の CSS の 適用先になります.
そして、ボタンのスタイルに rgb(66, 175, 250)
で カラーを設定します. ボタンの青のカラーが、上記 CSS の コピーでは上手く持ってこれないので、スタイル属性で適用しました.
これで、コントロール・ボタンのスタイルが公式デモのように [ > ] に なりました!
が、よくよくスライドを進めていくと、下スライドがある時に配置がずれてる…
配置を直し、ボタンを小さくする
どうも、元の [ ▶ ] の時に配置された CSS が 残っているようで、コピーしただけでは上書きできなかったようです.
再度 HTML に <style>
を 追加して大きさと配置を修正します.1
<style>
2
.reveal .controls .controls-arrow:before, .reveal .controls .controls-arrow:after { width: 1.4em; }
3
.reveal .controls .navigate-left, .reveal:not(.has-vertical-slides) .controls .navigate-left { top: 60px; left: 40px; }
4
.reveal .controls .navigate-right, .reveal:not(.has-vertical-slides) .controls .navigate-right { top: 60px; left: 60px; }
5
.reveal .controls .navigate-up, .reveal:not(.has-vertical-slides) .controls .navigate-up { top: 50px; left: 50px; }
6
.reveal .controls .navigate-down, .reveal:not(.has-vertical-slides) .controls .navigate-down { top: 70px; left: 50px; }
7
</style>
.controls-arrow:after { width: 1.4em; }
が ボタンの大きさになります.
その下の4つが、配置です. 大きさに合わせて配置を揃えていきます.
コンパクトになり、配置もそろいました!
最初のスライド と 下があるスライド の 場合は、少し動いてナビゲーションする
最初のスライドはよいとしても、メインのコンテンツ以外で動くものがあるのは、如何なものかとは思います. とはいえ縦方向にもスライドができるというは、あまりないのかなと思うと、ナビゲーションのために少し動いてもいいのかなと思い、公式デモから持ってきました.
まずは、少し動くアニメーションのスタイルです. 下矢印が動いて、戻るときに右矢印が動きます.
各%の数値を同じにすると、同時に動きます.1
<style>
2
@keyframes bounce-right {
3
0%, 35%, 50%, 65%, 75% { transform: translateX(0); }
4
45% { transform: translateX(2px); }
5
55% { transform: translateX(-1px); } }
6
@keyframes bounce-down {
7
0%, 10%, 25%, 40%, 50% { transform: translateY(2px); }
8
20% { transform: translateY(2px); }
9
30% { transform: translateY(2px); } }
10
</style>
続いて、最初のスライド と 下があるスライド の 際にアニメーションさせる JavaScript を 作ります.Reveal.addEventListener('ready', (event) => {})
は 上記ボタンの子要素を追加したときに記述した部分へ if(){}
を 追記します.1
<script>
2
Reveal.addEventListener('ready', (event) => {
3
if (Reveal.availableRoutes().right) { document.querySelector('.navigate-right').classList.add('highlight'); }
4
if (Reveal.availableRoutes().down) { document.querySelector('.navigate-down').classList.add('highlight'); }
5
});
6
7
Reveal.addEventListener('slidechanged', (event) => {
8
Array.from(document.querySelectorAll('aside.controls > button.highlight'), e => { e.classList.remove('highlight') });
9
10
if (event.indexh === 0 && event.indexv ===0) {
11
document.querySelector('.navigate-right').classList.add('highlight');
12
}
13
14
if (Reveal.availableRoutes().down) {
15
document.querySelector('.navigate-down').classList.add('highlight');
16
if (Reveal.availableRoutes().right) {
17
document.querySelector('.navigate-right').classList.add('highlight');
18
}
19
}
20
});
21
</script>
Reveal.addEventListener('ready', (event) => {});
で reveal.js の 描画が終わった後に、右矢印 と 下矢印 の それぞれが有効な場合に highlight
の CSS クラスを適用します. Reveal.availableRoutes()
で 指定する方向のスライドがあるかを判定できます.
Reveal.addEventListener('slidechanged', (event) => {});
では、スライドが変更された際のイベントで処理ができます.
まずは highlight
を すべて解除します.
続いて indexh
と indexv
が 0
、つまり最初のスライドの場合に、右矢印に highlight
を 設定.
そして、下方向がある場合に下矢印に highlight
し、さらに右方向がある場合は右矢印にも highlight
を 設定します.
これで、完成になります.
キャプチャは、動きが小さすぎて変化が分かるのが取れませんでした.
マイクロソフト伝説マネジャーの 世界№1プレゼン術
日本マイクロソフト株式会社 の 澤さん の プレゼンに関する書籍です. マイクロソフトテクノロジーセンター の センター長 を 勤め、マイクロソフト社のエバンジェリストを率いられています.
こちらの書籍は、プレゼンのためのテクニックというよりも、なぜプレゼンをするのか、なぜプレゼンが必要なのかという点から書かれています. ここでの「プレゼン」は 大人数を前にしたようなプレゼンではなく、営業だとか、自分の考えを伝えるためだとかにも当てはまり、ビジネス・スキルとしても役立ちます.
プレゼンを作る際にはいつも読み返す、基本の立ち位置として重宝しています.
プレゼンの極意はマンガに学べ
漫画家の三田紀房さん の 書籍です. ドラゴン桜 や エンゼルバンク などが有名ですが、ビジネス関係の書籍も出されています.
こちらは、その中でもプレゼンに関する書籍で、プレゼンを一つの物語として考えてみようというものになります. 一般的なプレゼンの書籍とは一線を画すので、好みが分かれるところだと思います. ご自身の漫画を例に、どのようにスライドを作るのかについて書かれています.
プレゼンだけではなく、アイデアの練り方などにもふれているのがよく、たまに読み返しては様々なことに思いを巡らせたりしています.
デザイン・センスとか、スキルがないのに、どうしてもスライドのデザインとか気になってしまうんですよね… 絵が描けたりする人がうらやましいです.
今回は公式デモを真似するので、CSS を 上手く当てはめることでできましたが、JS や CSS 本体にデモ用の改変が入っていたので、HTML 側だけで合わせるのが難しかったです. 上手くできてよかった.