使用PhantomJS的多个HTML页面的屏幕截图

时间:2015-01-06 16:19:28

标签: javascript phantomjs screenshot

正如大家在this github issue中提到的那样,phantomJS中的视口大小功能并不像很多人期望的那样。

我正在尝试为iPad上的网络应用截取屏幕截图。该网站有一个position:fixed;页脚和标题。当我拍摄截图时,我只希望能够在您第一次加载页面时看到屏幕上可以看到的内容,因此我使用以下代码将页面剪辑为我想要的大小。

page.clipRect = { top: 0, left: 0, width: 1024, height: 768 };

因为当我执行此操作并截取屏幕截图时,网站有一个position: fixed;页眉和页脚,当页面上的内容强制滚动时,页脚会丢失。 (它位于页面底部)

enter image description here

在回复中,一种解决方案是将您想要截取屏幕的页面加载到具有您偏好的高度和宽度的对象中,然后取一个对象的屏幕截图。

所有带有此功能的代码片段,假设您有一个您想截取屏幕截图的网址。我想截取多个html文件的截图。我根本不熟悉Javascript,我真的很难将这些解决方案合并到我的代码中。


This solution使用单个网页并使用json文件将其转换为多个不同大小的图像。

虽然this solution更符合我正在寻找的内容,但又是一个网页。请注意,iframe不起作用,iframe代码需要替换为具有数据属性且具有要加载的html页面值的对象。

还有一个final solution,它比其他人更完整,但又只是一个网址


我过去一直在使用以下代码,它与针对特定尺寸构建的网络应用程序完美配合,但是这个版本的构建方式略有不同,这就是屏幕截图成为噩梦的原因。

var system = require('system');
var dest = system.args[1];
var files = system.args[2].split(',');

function takeScreenshot(destName, index) {
    var page = require('webpage').create();

    // Open the target HTML file
    page.open(dest+'/'+destName+'/'+destName+'.html', function(status) {

        // Only capture 1024x768 area 
        page.clipRect = { top: 0, left: 0, width: 1024, height: 768 };

        // Save as PNG
        page.render(dest+'/'+destName+'/'+destName+'-full.png');

        // Send output to be caught by progress bar
        console.log('OK');

        // If the lop has finished exit, otherwise clean memory
        if(files.length == 0) {
        phantom.exit();
        } else {
            page.close();
            takeScreenshot(files.shift());
        }
    });

}

takeScreenshot(files.shift());

dest变量是屏幕截图的目的地。

文件是一个文件数组,我想截取屏幕截图。

1 个答案:

答案 0 :(得分:0)

final solution与现有代码结合起来应该很容易。我们的想法是将实际代码移动到一个函数中,并在完成上一个函数后使用新URL调用该函数。当您查看"最终解决方案"时,我们用当前页面完成的点用phantom.exit();表示。从那里你可以触发进一步的截图。

这是完整的脚本,从DEfusion版本修改:

var args = require('system').args,
    resourceWait  = 300,
    maxRenderWait = 10000,
    mode          = args[3] || 'iframe',
    dest          = args[1],
    files         = args[2].split(','),
    page          = require('webpage').create(),
    count         = 0,
    forcedRenderTimeout,
    renderTimeout;

page.viewportSize = { width: 1024, height : 768 };

function doRender() {
    page.render(filename);
    next();
}

page.onResourceRequested = function (req) {
    count += 1;
    clearTimeout(renderTimeout);
};

page.onResourceReceived = function (res) {
    if (!res.stage || res.stage === 'end') {
        count -= 1;
        if (count === 0) {
            clearTimeout(forcedRenderTimeout);
            renderTimeout = setTimeout(doRender, resourceWait);
        }
    }
};

page.onConsoleMessage = function (msg) {
    console.log("from page: " + msg);
};

function evaluateJsWithArgs(func) {
    var args = [].slice.call(arguments, 1);
    var fn = "function() { return (" + func.toString() + ").apply(this, " + JSON.stringify(args) + "); }";
    return page.evaluate(fn);
};

function next(error){
    if (!error) {
        if (files.length == 0){
            phantom.exit();
        } else {
            takeScreenshot(files.shift());
        }
    }
}

function takeScreenshot(file){
    var url = dest+'/'+file+'/'+file+'.html';
    filename = dest+'/'+file+'/'+file+'-full.png';
    if(mode == 'iframe') {
        // use iFrame
        page.open('about:blank', function (status) {
            if (status !== "success") {
                console.log('Unable to load url');
                next(true);
            } else {
                page.includeJs(
                    "https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js",
                    function() {
                        evaluateJsWithArgs(
                            function(url, w, h) {
                                $('body')
                                    .css({margin: 0, padding: 0})
                                    .append('<object data="' + url + '" width="'+ w + '" height="' + h + '" id="screen-frame" />');
                                $('#screen-frame')
                                    .width(w)
                                    .height(h);
                            },
                            url,
                            page.viewportSize.width,
                            page.viewportSize.height
                        );
                    }
                );

                forcedRenderTimeout = setTimeout(function () {
                    doRender();
                }, maxRenderWait);
            }
        });
    } else {
        // resize body
        page.open(url, function(status) {
            if (status !== "success") {
                console.log('Unable to load url');
                next(true);
            } else {
                page.includeJs(
                    "https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js",
                    function() {
                        evaluateJsWithArgs(
                            function(w,h) {
                               $('body, html').css({
                                    width: w + 'px',
                                    height: h + 'px',
                                    overflow: 'hidden'
                               });
                            },
                            page.viewportSize.width,
                            page.viewportSize.height
                        );

                        forcedRenderTimeout = setTimeout(function () {
                            doRender();
                        }, maxRenderWait);
                    }
                );
            }
        });
    }
}

takeScreenshot(files.shift());