Screenshots de qualquer dimensão, com o PhantomJS
O problema
Às vezes precisamos de um screenshot de uma página web com uma resolução diferente da do nosso ecrã. Se essa resolução for menor que a do nosso ecrã, a coisa até se resolve. Redimensiona-se a janela para a dimensão pretendida e usa-se um dos muitos plugins disponíveis, embora nem sempre sejam muito fiáveis se quisermos uma resolução exacta. Se a resolução for maior, torna-se um bocado mais complicado. Se precisarmos de simular uma pixel density maior (aka retina), ainda pior.
Deparei-me com este problema quando precisei de criar screenshots para o meu portefólio. Comprei um daqueles ficheiros .psd com computadores e telemóveis de vários tamanhos. Por alguma razão todos estes ficheiros apresentam produtos Apple e, para funcionar correctamente, precisava de screenshots com uma resolução idêntica à dos Macs e iPhones.
A solução
É aqui que entra o PhantomJS. Uma implementação do Webkit que pode ser manipulada via JavaScript. Tem vários casos de uso. Entre eles, o que nos interessa para hoje, a geração de capturas de ecrã.
O script para fazer isso é bastante simples.
var webPage = require('webpage'); var page = webPage.create(); // o tamanho do screenshot page.viewportSize = { width: 2880, height: 1800 }; // o endereço da página a capturar page.open("http://zecipriano.com/", function start(status) { page.evaluate(function () { // a escala do conteúdo, 1 para normal, 2 para uma espécie de retina var scale = 2; document.body.style.webkitTransform = "scale(" + scale + ")"; document.body.style.webkitTransformOrigin = "0% 0%"; document.body.style.width = 100/scale + "%"; }); // o ficheiro a gravar, a extensão define o formato page.render('output.png'); phantom.exit(); });
Para obter um screenshot basta gravar este script num ficheiro (por exemplo screenshot.js
), editar com os valores pretendidos e executar o PhamtonJS.
phantomjs screenshot.js
O scale = 2 é o valor que vai simular um ecrã com densidade 2x (só mais ou menos, ver notas). Para um screenshot normal, o valor deve ser 1.
De notar que isto é a forma mais simples de resolver o problema. O script podia ser melhorado de vários formas, nomeadamente aceitar os valores como parâmetros em vez de serem hardcoded no script.
Algumas questões:
- Usar o scale = 2 não emula completamente um ecrã de alta densidade. Apenas duplica o tamanho do conteúdo, o device pixel ratio continua a ser 1. O que elimina, por exemplo, a possibilidade de gerar correctamente um screenshot de um ecrã de telemóvel.
- A versão actual (1.9) não suporta Google Web Fonts (mais especificamente ficheiros .woff). Apenas a próxima versão (2.0) resolve este problema. Podem encontrar um build da versão 2, aqui.
- A altura do viewport parece não ter influência na altura do screenshot. Mas depois de ter o screenshot é fácil de cortar à dimensão correcta.