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はこれまでヘッドレステストなどで利用していましたが、こういう用途でも遊べると楽しいですね。資料用にサイトのスクリーンショットを大量に撮りたいときにも便利かもしれません。