phantomjs自动截图生成图片

https://www.jianshu.com/p/41d5e08af0a7

https://www.cnblogs.com/bangejingting/p/6907628.html

有时候我们需要定时的生成一些报表图片,或者通过钉钉等发送给对应用户或群组;

第一步,本地生成报表,可以用baiduEchart等

https://www.echartsjs.com/zh/tutorial.html#%E4%B8%AA%E6%80%A7%E5%8C%96%E5%9B%BE%E8%A1%A8%E7%9A%84%E6%A0%B7%E5%BC%8F

 

第二部,自动渲染图片,进行截图

springMvc.xml添加:
<bean id="beetlConfig" class="org.beetl.ext.spring.BeetlGroupUtilConfiguration"
      init-method="init">
    <property name="configFileResource" value="classpath:beetl.properties" />
</bean>

<bean id="beelViewResolver" class="org.beetl.ext.spring.BeetlSpringViewResolver">
    <property name="suffix" value=".html" />
    <property name="contentType" value="text/html;charset=UTF-8" />
    <property name="order" value="0"/>
    <property name="config" ref="beetlConfig"/>
    <property name="cache" value="true"/>
    <property name="allowSessionOverride" value="true" />
    <property name="allowRequestOverride" value="true" />
</bean>


maven依赖:
<!-- 在线生成图片导出 -->
<dependency>
    <groupId>com.ibeetl</groupId>
    <artifactId>beetl</artifactId>
    <version>2.5.0</version>
</dependency>
<dependency>
    <groupId>com.dingtalk.chatbot</groupId>
    <artifactId>dingtalk-chatbot-sdk</artifactId>
    <version>0.9.0-SNAPSHOT</version>
</dependency>
try {
    //渲染模版,生成HTML代码
    Template template = groupTemplate.getTemplate(templateFile);
    template.binding("data", data);
    template.binding("title", title);
    template.binding("subTitle", subTitle);
    String html = template.render();

    return html;
} catch (Exception e) {
    log.warn("convertDataToGraph error", e);
}
//写入到文件
private String convertHtmlToImage(String html, EnvType env) throws IOException {
    //写入到文件
    String[] commands = null;
        writeToFile(html, API_RANK_RELEASE_HTML);
        commands = new String[]{"bash", "-c", phantomPath + " " + reportPath + CAPTURE_RELEASE_JS};
    //生成图片
    int status = 1;
 
        Process process = Runtime.getRuntime().exec(commands, null, new File(reportPath));
        status = process.waitFor();

    //执行名称出错,直接抛出异常
    if (status != 0) {
        log.error("failed to generate the image status code:{}", status);
        throw new RuntimeException("failed to generate the image status code: " + status);
    }

    return imageTempPath;
}
private void writeToFile(String html, String tempHtmlName) throws IOException {
    BufferedWriter writer = null;
    String fileName = reportPath + tempHtmlName;
    try {

        File oldFile = new File(fileName);
        if (oldFile.exists()) {
            oldFile.delete();
        }
        writer = new BufferedWriter(new FileWriter(fileName));
        writer.write(html);

    } finally {
        if (writer != null) {
            writer.close();
        }
    }
}
beetl.properties
#\u914D\u7F6E\u5F15\u64CE\u5B9E\u73B0\u7C7B
ENGINE=org.beetl.core.engine.FastRuntimeEngine
#\u6307\u5B9A\u4E86\u5360\u4F4D\u7B26\u53F7\uFF0C\u9ED8\u8BA4\u662F${ }.\u4E5F\u53EF\u4EE5\u6307\u5B9A\u4E3A\u5176\u4ED6\u5360\u4F4D\u7B26
DELIMITER_PLACEHOLDER_START=${
DELIMITER_PLACEHOLDER_END=}
#\u6307\u5B9A\u4E86\u8BED\u53E5\u7684\u5B9A\u754C\u7B26\u53F7\uFF0C\u9ED8\u8BA4\u662F<% %>,\u4E5F\u53EF\u4EE5\u6307\u5B9A\u4E3A\u5176\u4ED6\u5B9A\u754C\u7B26\u53F7
#DELIMITER_STATEMENT_START=@
#DELIMITER_STATEMENT_END=null
#\u6307\u5B9AIO\u8F93\u51FA\u6A21\u5F0F\uFF0C\u9ED8\u8BA4\u662FFALSE,\u5373\u901A\u5E38\u7684\u5B57\u7B26\u8F93\u51FA\uFF0C\u518D\u8003\u8651\u9AD8\u6027\u80FD\u60C5\u51B5\u4E0B\uFF0C\u53EF\u4EE5\u8BBE\u7F6E\u6210true
DIRECT_BYTE_OUTPUT = true
#\u6307\u5B9A\u4E86\u652F\u6301HTML\u6807\u7B7E\uFF0C\u4E14\u7B26\u53F7\u4E3A#\uFF08\u53EA\u80FD\u7528\u4E00\u4E2A\u7B26\u53F7\u6807\u793A\uFF09\uFF0C\u9ED8\u8BA4\u914D\u7F6E\u4E0B\uFF0C\u6A21\u677F\u5F15\u64CE\u8BC6\u522B<#tag ></#tag>
#\u8FD9\u6837\u7684\u7C7B\u4F3Chtml\u6807\u7B7E\uFF0C\u5E76\u80FD\u8C03\u7528\u76F8\u5E94\u7684\u6807\u7B7E\u51FD\u6570\u3002
HTML_TAG_SUPPORT = true
HTML_TAG_FLAG = #
#\u6307\u5B9A\u5141\u8BB8\u672C\u5730Class\u76F4\u63A5\u8C03\u7528
NATIVE_CALL = TRUE
#\u6307\u5B9A\u6A21\u677F\u5B57\u7B26\u96C6\u662FUTF-8
TEMPLATE_CHARSET = UTF-8
#\u6307\u5B9A\u5F02\u5E38\u7684\u89E3\u6790\u7C7B\uFF0C\u9ED8\u8BA4\u662FConsoleErrorHandler\uFF0C\u4ED6\u5C06\u5728render\u53D1\u751F\u5F02\u5E38\u7684\u65F6\u5019\u5728\u540E\u53F0\u6253\u5370\u51FA\u9519\u8BEF\u4FE1\u606F(System.out)\u3002
ERROR_HANDLER = org.beetl.core.ConsoleErrorHandler
#\u6307\u5B9A\u4E86\u672C\u5730Class\u8C03\u7528\u7684\u5B89\u5168\u7B56\u7565
NATIVE_SECUARTY_MANAGER= org.beetl.core.DefaultNativeSecurityManager
#\u6307\u5B9A\u4E86\u9ED8\u8BA4\u4F7F\u7528\u7684\u6A21\u677F\u8D44\u6E90\u52A0\u8F7D\u5668
RESOURCE_LOADER=org.beetl.core.resource.ClasspathResourceLoader
#\u914D\u7F6E\u4E86\u662F\u5426\u8FDB\u884C\u4E25\u683CMVC\uFF0C\u901A\u5E38\u60C5\u51B5\u4E0B\uFF0C\u6B64\u5904\u8BBE\u7F6E\u4E3Afalse.
MVC_STRICT = FALSE
#\u8D44\u6E90\u914D\u7F6E\uFF0Cresource\u540E\u7684\u5C5E\u6027\u53EA\u9650\u4E8E\u7279\u5B9AResourceLoader
#classpath \u6839\u8DEF\u5F84(\u5176\u5B9E\u5C31\u662F\u524D\u7F00\u7684\u914D\u7F6E)
RESOURCE.root= /report/
#\u662F\u5426\u68C0\u6D4B\u6587\u4EF6\u53D8\u5316
RESOURCE.autoCheck=true
#\u81EA\u5B9A\u4E49\u811A\u672C\u65B9\u6CD5\u6587\u4EF6\u7684Root\u76EE\u5F55\u548C\u540E\u7F00
#RESOURCE.functionRoot = functions
#RESOURCE.functionSuffix = fn
#\u81EA\u5B9A\u4E49\u6807\u7B7E\u6587\u4EF6Root\u76EE\u5F55\u548C\u540E\u7F00
#RESOURCE.tagRoot = htmltag
#RESOURCE.tagSuffix = tag


##### \u6269\u5C55 ##############
## \u5185\u7F6E\u7684\u65B9\u6CD5
#FN.date = org.beetl.ext.fn.DateFunction
#FN.nvl = org.beetl.ext.fn.NVLFunction
#FN.debug = org.beetl.ext.fn.DebugFunction
#FN.exist = org.beetl.ext.fn.CheckExistFunction
#FN.printf = org.beetl.ext.fn.Printf
#FN.decode = org.beetl.ext.fn.DecodeFunction
#FN.assert = org.beetl.ext.fn.AssertFunction
#FN.print = org.beetl.ext.fn.Print
#FN.println = org.beetl.ext.fn.Println
#FN.trunc = org.beetl.ext.fn.TruncFunction
#FN.trim = org.beetl.ext.fn.TruncFunction2
#FN.empty = org.beetl.ext.fn.EmptyFunction
#FN.qmark = org.beetl.ext.fn.QuestionMark
#FN.isEmpty = org.beetl.ext.fn.EmptyExpressionFunction
#FN.parseInt = org.beetl.ext.fn.ParseInt
#FN.parseDouble= org.beetl.ext.fn.ParseDouble
#FN.range = org.beetl.ext.fn.Range
##\u5185\u7F6E\u7684\u529F\u80FD\u5305
#FNP.strutil = org.beetl.ext.fn.StringUtil
#FNP.array = org.beetl.ext.fn.ArrayUtil

##\u5185\u7F6E\u7684\u683C\u5F0F\u5316\u51FD\u6570
#FT.dateFormat =  org.beetl.ext.format.DateFormat
#FT.numberFormat =  org.beetl.ext.format.NumberFormat
##\u5185\u7F6E\u7684\u9ED8\u8BA4\u683C\u5F0F\u5316\u51FD\u6570
#FTC.java.util.Date = org.beetl.ext.format.DateFormat
#FTC.java.sql.Date = org.beetl.ext.format.DateFormat
#FTC.java.sql.Time = org.beetl.ext.format.DateFormat
#FTC.java.sql.Timestamp = org.beetl.ext.format.DateFormat
#FTC.java.lang.Short = org.beetl.ext.format.NumberFormat
#FTC.java.lang.Long = org.beetl.ext.format.NumberFormat
#FTC.java.lang.Integer = org.beetl.ext.format.NumberFormat
#FTC.java.lang.Float = org.beetl.ext.format.NumberFormat
#FTC.java.lang.Double = org.beetl.ext.format.NumberFormat
#FTC.java.math.BigInteger = org.beetl.ext.format.NumberFormat
#FTC.java.math.BigDecimal = org.beetl.ext.format.NumberFormat
#FTC.java.util.concurrent.atomic.AtomicLong = org.beetl.ext.format.NumberFormat
#FTC.java.util.concurrent.atomic.AtomicInteger = org.beetl.ext.format.NumberFormat

## \u6807\u7B7E\u7C7B
#TAG.include= org.beetl.ext.tag.IncludeTag
#TAG.includeFileTemplate= org.beetl.ext.tag.IncludeTag
#TAG.layout= org.beetl.ext.tag.LayoutTag
#TAG.delete= org.beetl.ext.tag.DeleteTag
#TAG.htmltag= org.beetl.ext.tag.HTMLTagSupportWrapper
#WEBAPP_EXT = com.ximalaya.southgate.admin.beetl.GlobalExt
captureRelease.js

var page = require('webpage').create();
page.viewportSize = {
  width: 1920,
  height: 1080,
  orientation: 'landscape'
};
page.open('apiRankRelease.html', function() {

  window.setTimeout(function () {
    page.render('apiRankRelease.png');
    page.close();
    phantom.exit();
  }, 3000);

});
reportPieRelease.html

<!DOCTYPE html>
<html style="height: 100%">
<head>
  <meta charset="utf-8">
  <style>
    @font-face {
      font-family: "PingF";
      src: url("font/PingFang-SC-Bold.ttf"),url("font/PingFang-SC-Light.ttf"),url("font/PingFang-SC-Regular.ttf");
    }
    body {
      font-family: "PingF";
    }
  </style>
</head>
<body style="height: 100%; margin: 0">
<div id="container" style=" width: 1920px;height: 1080px"></div>
<div id="text">
  push
</div>
<!--<script type="text/javascript" src="../lib/echarts/4/echarts.min.js"></script>-->
<script src="http://echarts.baidu.com/dist/echarts.min.js"></script>
<script type="text/javascript">

    setTimeout(function () {
        var text = document.getElementById("text");
        text.style.display="none";

        var dom = document.getElementById("container");
        var myChart = echarts.init(dom);

        var data = genData(20);

        option = {
            title : {
                text: '${title}',
                subtext: '${subTitle}',
                x:'center',
                textStyle:{
                    fontFamily: "PingF",
                    fontSize:25
                },
                subtextStyle:{
                    fontFamily: "PingF",
                    fontSize:23
                }
            },
            tooltip : {
                trigger: 'item',
                formatter: "{a} <br/>{b} : {c} ({d}%)",
                textStyle: {
                    fontFamily: "PingF",
                    fontSize: 20
                }
            },
            legend: {
                type: 'scroll',
                orient: 'vertical',
                right: 10,
                top: 80,
                bottom: 20,
                data: data.legendData,
                selected: data.selected,
                textStyle: {
                    fontFamily: "PingF",
                    fontSize: 23
                }
            },
            series : [
                {
                    name: '姓名',
                    type: 'pie',
                    radius : '35%',
                    center: ['30%', '45%'],
                    data: data.seriesData,
                    itemStyle: {
                        emphasis: {
                            shadowBlur: 10,
                            shadowOffsetX: 0,
                            shadowColor: 'rgba(0, 0, 0, 0.5)'
                        }
                    },
                    label:{            //饼图图形上的文本标签
                        normal:{
                            show:true,
                            textStyle : {
                                fontFamily: "PingF",
                                fontSize : 18    //文字的字体大小
                            }
                        }
                    }
                }
            ]
        };

        function genData(count) {

            var legendData = [];
            var seriesData = [];
            var selected = {};
            var i = 0;
        <%for(apiItem in data){%>
                name = '${apiItem.product}';
                legendData.push(name);
                seriesData.push({
                    name: name,
                    value: ${apiItem.amount}
                });
                i++;
                selected[name] = i < 10;
            <%}%>

            return {
                legendData: legendData,
                seriesData: seriesData,
                selected: selected
            };
        };

        if (option && typeof option === "object") {
            myChart.setOption(option, true);
        }
    }, 1000);
</script>
</body>
</html>

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值