使用phantomJs服务器端导出Echarts图片

转载自:http://blog.csdn.net/zor_chen/article/details/31371501

目录

背景

在使用Echarts过程中,有需求在页面上图表显示和服务器端导出报表。在Echarts中,原生态提供了getImage()方法,但是都需要在页面上生成。事实上,可以通过页面上使用getImage()获得base64 encode的图片数据,传输至服务器端导出图片。但是在项目需求中,有一种场景在导出报表时,页面可能不需要生成图片。因此只能调研是否在服务器端直接生成。

思路

phantomJs作为一个headless浏览器,支持网页截图。通过调用phantomJs,传入Echarts生成图表所需的options,与在页面上类似的方法,调用phantomJs的webpage模块,通过使用webpage.evaluate()在页面中生成div容器,调用echarts.init(container)生成图表,最终调用phantomJs的webpage.render()生成图片。

代码

(function() {
    var system = require('system');
    var fs = require('fs');
    var config = {
        // define the location of js files
        JQUERY : 'jquery.1.9.1.min.js',
        ESL : 'esl.js',
        ECHARTS : 'echarts-plain.js',
        // default container width and height
        DEFAULT_WIDTH : '800',
        DEFAULT_HEIGHT : '400'
    }, parseParams, render, pick, usage;

    usage = function() {
        console.log("\nUsage: phantomjs echarts-convert.js -options options -outfile filename -width width -height height"
                        + "OR"
                        + "Usage: phantomjs echarts-convert.js -infile URL -outfile filename -width width -height height\n");
    };

    pick = function() {
        var args = arguments, i, arg, length = args.length;
        for (i = 0; i < length; i += 1) {
            arg = args[i];
            if (arg !== undefined && arg !== null && arg !== 'null' && arg != '0') {
                return arg;
            }
        }
    };

    parseParams = function() {
        var map = {}, i, key;
        if (system.args.length < 2) {
            usage();
            phantom.exit();
        }
        for (i = 0; i < system.args.length; i += 1) {
            if (system.args[i].charAt(0) === '-') {
                key = system.args[i].substr(1, i.length);
                if (key === 'infile') {
                    // get string from file
                    // force translate the key from infile to options.
                    key = 'options';
                    try {
                        map[key] = fs.read(system.args[i + 1]).replace(/^\s+/, '');
                    } catch (e) {
                        console.log('Error: cannot find file, ' + system.args[i + 1]);
                        phantom.exit();
                    }
                } else {
                    map[key] = system.args[i + 1];
                }
            }
        }
        return map;
    };

    render = function(params) {
        var page = require('webpage').create(), createChart;

        page.onConsoleMessage = function(msg) {
            console.log(msg);
        };

        page.onAlert = function(msg) {
            console.log(msg);
        };

        createChart = function(inputOption, width, height) {
            var counter = 0;
            function decrementImgCounter() {
                counter -= 1;
                if (counter < 1) {
                    console.log(messages.imagesLoaded);
                }
            }

            function loadScript(varStr, codeStr) {
                var script = $('<script>').attr('type', 'text/javascript');
                script.html('var ' + varStr + ' = ' + codeStr);
                document.getElementsByTagName("head")[0].appendChild(script[0]);
                if (window[varStr] !== undefined) {
                    console.log('Echarts.' + varStr + ' has been parsed');
                }
            }

            function loadImages() {
                var images = $('image'), i, img;
                if (images.length > 0) {
                    counter = images.length;
                    for (i = 0; i < images.length; i += 1) {
                        img = new Image();
                        img.onload = img.onerror = decrementImgCounter;
                        img.src = images[i].getAttribute('href');
                    }
                } else {
                    console.log('The images have been loaded');
                }
            }
            // load opitons
            if (inputOption != 'undefined') {
                // parse the options
                loadScript('options', inputOption);
                // disable the animation
                options.animation = false;
            }

            // we render the image, so we need set background to white.
            $(document.body).css('backgroundColor', 'white');
            var container = $("<div>").appendTo(document.body);
            container.attr('id', 'container');
            container.css({
                width : width,
                height : height
            });

            // render the chart
            var myChart = echarts.init(container[0]);
            myChart.setOption(options);
            // load images
            loadImages();
        };

        // parse the params
        page.open("about:blank", function(status) {
            // inject the dependency js
            page.injectJs(config.JQUERY);
            page.injectJs(config.ESL);
            page.injectJs(config.ECHARTS);

            var width = pick(params.width, config.DEFAULT_WIDTH);
            var height = pick(params.height, config.DEFAULT_HEIGHT);

            // create the chart
            page.evaluate(createChart, params.options, width, height);

            // define the clip-rectangle
            page.clipRect = {
                top : 0,
                left : 0,
                width : width,

                height : height
            };
            // render the image
            page.render(params.outfile);
            console.log('render complete:' + params.outfile);
            // exit
            phantom.exit();
        });
    };
    // get the args
    var params = parseParams();

    // validate the params
    if (params.options === undefined || params.options.length === 0) {
        console.log("ERROR: No options or infile found.");
        usage();
        phantom.exit();
    }
    // set the default out file
    if (params.outfile === undefined) {
        var tmpDir = fs.workingDirectory + '/tmp';
        // exists tmpDir and is it writable?
        if (!fs.exists(tmpDir)) {
            try {
                fs.makeDirectory(tmpDir);
            } catch (e) {
                console.log('ERROR: Cannot make tmp directory');
            }
        }
        params.outfile = tmpDir + "/" + new Date().getTime() + ".png";
    }

    // render the image
    render(params);
}());

使用方法:

  1. phantomjs echarts-convert.js -options options -outfile filename -width width -height height
  2. phantomjs echarts-convert.js -infile URL -outfile filename -width width -height height

例子

options文件内容:

{
    title : {
        text: '世界人口总量',
        subtext: '数据来自网络'
    },
    tooltip : {
        trigger: 'axis'
    },
    legend: {
        data:['2011年', '2012年']
    },
    calculable : true,
    xAxis : [
        {
            type : 'value',
            boundaryGap : [0, 0.01]
        }
    ],
    yAxis : [
        {
            type : 'category',
            data : ['巴西','印尼','美国','印度','中国','世界人口(万)']
        }
    ],
    series : [
        {
            name:'2011年',
            type:'bar',
            data:[18203, 23489, 29034, 104970, 131744, 630230]
        },
        {
            name:'2012年',
            type:'bar',
            data:[19325, 23438, 31000, 121594, 134141, 681807]
        }
    ]
}

命令行方法:

bin/phantomjs echarts/echarts-convert.js -infile options -outfile test.png

导出图片

这里写图片描述


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值