phantomjsでscroll後の画像がrenderできない


問題

表題の通り。
会社のメンバーから質問きたので、解決方法を調査して答えました。
そのときの知見として残しておきます。

phantomjsの準備

ここで書くことじゃないけども、一応こんな感じ

setup
echo '{"scripts": {"start": "phantomjs script.js"}}' >> package.json
echo 'console.log("Hello, World!"); phantom.exit()' >> script.js
npm install --save-dev phantom phantomjs
npm start

楽ちんですね

やろうとしたこと

  • webページを開いて
  • jsで window.scrollTo(0, 1000) して
  • スクロール後の画像を保存
script.js
var page = require('webpage').create();

page.viewportSize = { width: 320, height: 480 };
page.clipRect = { top: 0, left: 0, width: 320, height: 480 };

page.open('https://qiita.com/nabepon/items/cd6086bb4ecd6d8ce812', function() {
  var position = page.evaluate(function() {
    window.scrollTo(0, 1000);
    return window.scrollY;
  });
  console.log(position);
  page.render('screenshot.png');
  phantom.exit();
});

失敗結果

どうなったかというと、

console.log(position);

の出力は問題なく 1000 と出ている。
にも関わらず、撮れたスクショはスクロールしていない。
???

解決方法

以下のように、pageオブジェクトにscroll位置を設定しないといけないらしい

page.scrollPosition = {top: 1000, left: 0}

なるほど、というわけでこういうコードを書いて解決した

script.js
page.open('https://qiita.com/nabepon/items/cd6086bb4ecd6d8ce812', function() {
  var position = page.evaluate(function() {
    window.scrollTo(0, 1000);
    return JSON.stringify({
      top: window.scrollY,
      left: window.scrollX,
    });
  });
  page.scrollPosition = JSON.parse(position);

  console.log(position);
  page.render('screenshot.png');
  phantom.exit();
});

成功結果

無事scrollした画像が撮れました。
それにしてもphantomjsを使うとES5で書かないといけず非常につらい。babel入れるのも少し面倒でした。
なぜ今phantomjsを使っているのだろう。