Reveal.jsのスクリーンショットをPhantomJSでガンガン撮る
Posted: Updated:
Gistぺたり
短いながら、phantomjsの便利なAPIが詰まってたので貼ってみた。
% phantomjs shot.js
Reveal.jsって?
いわゆるHTMLスライドのフレームワークです。最初からある程度かっこよく作られていて、そのままでも十分使えると思います。APIもちゃんと整備されているので、コントロールを追加することもできます。
- 複数のテーマが用意されている
- 複数のトランジションが用意されている
- Markdownで書ける(
data-markdownを付与したsectionのみ) - nodeでKeynoteみたいなスライドウインドウ+スピーカーノートウインドウの連携ができる
などなど。今用意している最中のスライドでは、これを使ってみています。
なんでスクリーンショット?
普通にPDFで出力するだけであれば、Reveal.jsのPDF Exportを参考に、?print-pdfを末尾につけてアクセスすれば良いです。きれいに出力してくれます。
ただし、data-stateというのを絡めた、背景全面のコントロールにはJavaScriptが必要なため、通常の印刷ではそのあたりの再現がうまくいきません。フォントのこともあるしなー、とか色々ございまして。
ならば丸々、スクリーンショットとして撮ってしまえばいいじゃない → 手作業はめんどう → phantomjsでスクショとる遊びしたことあった!という流れです。
説明
全体としては、phantomjsでページを開いて、順番にスライドを進めながら都度pngファイルを出力する、という簡単な処理です。
phantomjsでWebページを開く
Web Page moduleのあたりを利用しています。
var page = require('webpage').create();
var url = 'http://localhost:1947/';
page.viewportSize = {
width: 1024,
height: 768
};
page.open(url, function() {
//...
});
ページを開いたあとの処理は、page.openのコールバックとして渡します。
スライドの枚数を数える
ループでまわす前に、スライドの枚数を数えます。
iz = page.evaluate(function() {
return document.querySelector('.slides').children.length;
});
page.evaluateで、ページ内のJavaScriptにアクセスできて、returnで結果を返せば値を取得できます。これ楽しい。
ページをめくる
ループをぶん回してキューを作って1枚ずつ処理させてるだけですが、ページめくりも先ほどと同様にpage.evaluateで行えます。
page.evaluate(function(i) {
Reveal.navigateTo(i);
}, i);
page.evaluateへの引数として、変数を送ることもできるので、それをReveal側のnavigateToメソッドに渡してページを進めていきます。
PNGでスクショを撮る
page.renderでスクリーンショットを撮ります。
指定したファイル名で拡張子を判別してくれますが、これをpdfにすると印刷のPDF出力も利用できたりします。ほんとに印刷と同じような扱いになるので、今回のケースでは意味がありません。
setTimeout(function() {
var next = queue[(i+1)];
page.render('./shot/shot-'+i+'.png');
if (next) {
next();
} else {
phantom.exit();
}
}, 1000);
タイマーを仕込んでいるのは、主にスライドのトランジションが終わるまでの待ち時間です。トランジションをオフにすれば、ある程度高速で回せますが、タイマーなしだとReveal側のJS処理が追いついていなかったりするので、少なくとも100ms程度はあったほうがよいでしょう。
キューがなくなったらphantom.exitで処理を終えます。
phantomjs楽しいなぁ
phantomjsはこれまでヘッドレステストなどで利用していましたが、こういう用途でも遊べると楽しいですね。資料用にサイトのスクリーンショットを大量に撮りたいときにも便利かもしれません。