后端使用pyecharts画图并输出为图片保存

带区域标注的线图

#coding=utf-8
from __future__ import unicode_literals

from pyecharts import Line
from pyecharts.conf import PyEchartsConfig
from pyecharts.engine import EchartsEnvironment
from pyecharts.utils import write_utf8_html_file

attr = ["2018/03/11", "2018/03/18", "2018/03/25", "2018/04/01", "2018/04/08"]
selectedColumn = "Visitor Count"
column = 'Column: {}'.format(selectedColumn)
line = Line(column)
v1 = [661.0, 359.0, 358.0, 536.0, 391.0]
v2 = [102.0, 906.0, 84.0, 878.0, 115.0]
line.add("VP1", attr,v1 ,mark_point=["average", "max", "min"])
line.add("VP2", attr, v2,mark_point=["average", "max", "min"])
line.add("Filter", attr, [430]*len(v1), is_fill=True, 
         area_opacity=0.3, is_smooth=True)#,is_toolbox_show=False
config = PyEchartsConfig(echarts_template_dir='./')
env = EchartsEnvironment(pyecharts_config=config)
tpl = env.get_template('chart_template.html')
html = tpl.render(line=line)
write_utf8_html_file('chart_out.html', html)

模板文件内容

<!DOCTYPE html>
<html lang="zh-CN">
    <script src='./echarts.min.js'></script>
    <!--注意这里的js文件路径一定要对得上-->
<head>
    <meta charset="UTF-8">
    <title>Visitor Record echarts</title>
    {{ echarts_js_dependencies(line) }}
</head>
<body>
    {{ echarts_container(line) }}
    {{ echarts_js_content(line) }}
</body>
</html>

运行结果(chart_out.html):

这里写图片描述

以上基本的使用就OK了,但是我们的需求是将页面中的canvas保存为图片,下面将介绍我最近项目中使用的一种方法:

使用到的工具是phantomjs

这里写图片描述

具体安装就不多说了

phantomjs --help
Usage:
   phantomjs [switchs] [options] [script] [argument [argument [...]]]

Options:
  --cookies-file=<val>                 Sets the file name to store the persistent cookies
  --config=<val>                       Specifies JSON-formatted configuration file
  --debug=<val>                        Prints additional warning and debug message: 'true' or 'false' (default)
  --disk-cache=<val>                   Enables disk cache: 'true' or 'false' (default)
  --disk-cache-path=<val>              Specifies the location for the disk cache
  --ignore-ssl-errors=<val>            Ignores SSL errors (expired/self-signed certificate errors): 'true' or 'false' (default)
  --load-images=<val>                  Loads all inlined images: 'true' (default) or 'false'
  --local-url-access=<val>             Allows use of 'file:///' URLs: 'true' (default) or 'false'
  --local-storage-path=<val>           Specifies the location for local storage
  --local-storage-quota=<val>          Sets the maximum size of the local storage (in KB)
  --offline-storage-path=<val>         Specifies the location for offline storage
  --offline-storage-quota=<val>        Sets the maximum size of the offline storage (in KB)
  --local-to-remote-url-access=<val>   Allows local content to access remote URL: 'true' or 'false' (default)
  --max-disk-cache-size=<val>          Limits the size of the disk cache (in KB)
  --output-encoding=<val>              Sets the encoding for the terminal output, default is 'utf8'
  --remote-debugger-port=<val>         Starts the script in a debug harness and listens on the specified port
  --remote-debugger-autorun=<val>      Runs the script in the debugger immediately: 'true' or 'false' (default)
  --proxy=<val>                        Sets the proxy server, e.g. '--proxy=http://proxy.company.com:8080'
  --proxy-auth=<val>                   Provides authentication information for the proxy, e.g. ''-proxy-auth=username:password'
  --proxy-type=<val>                   Specifies the proxy type, 'http' (default), 'none' (disable completely), or 'socks5'
  --script-encoding=<val>              Sets the encoding used for the starting script, default is 'utf8'
  --script-language=<val>              Sets the script language instead of detecting it: 'javascript'
  --web-security=<val>                 Enables web security, 'true' (default) or 'false'
  --ssl-protocol=<val>                 Selects a specific SSL protocol version to offer. Values (case insensitive): TLSv1.2, TLSv1.1, TLSv1.0, TLSv1 (same as v1.0), SSLv3, or ANY. Default is to offer all that Qt thinks are secure (SSLv3 and up). Not all values may be supported, depending on the system OpenSSL library.
  --ssl-ciphers=<val>                  Sets supported TLS/SSL ciphers. Argument is a colon-separated list of OpenSSL cipher names (macros like ALL, kRSA, etc. may not be used). Default matches modern browsers.
  --ssl-certificates-path=<val>        Sets the location for custom CA certificates (if none set, uses environment variable SSL_CERT_DIR. If none set too, uses system default)
  --ssl-client-certificate-file=<val>  Sets the location of a client certificate
  --ssl-client-key-file=<val>          Sets the location of a clients' private key
  --ssl-client-key-passphrase=<val>    Sets the passphrase for the clients' private key
  --webdriver=<val>                    Starts in 'Remote WebDriver mode' (embedded GhostDriver): '[[<IP>:]<PORT>]' (default '127.0.0.1:8910') 
  --webdriver-logfile=<val>            File where to write the WebDriver's Log (default 'none') (NOTE: needs '--webdriver') 
  --webdriver-loglevel=<val>           WebDriver Logging Level: (supported: 'ERROR', 'WARN', 'INFO', 'DEBUG') (default 'INFO') (NOTE: needs '--webdriver') 
  --webdriver-selenium-grid-hub=<val>  URL to the Selenium Grid HUB: 'URL_TO_HUB' (default 'none') (NOTE: needs '--webdriver') 
  -w,--wd                              Equivalent to '--webdriver' option above
  -h,--help                            Shows this message and quits
  -v,--version                         Prints out PhantomJS version

Any of the options that accept boolean values ('true'/'false') can also accept 'yes'/'no'.

Without any argument, PhantomJS will launch in interactive mode (REPL).

Documentation can be found at the web site, http://phantomjs.org.

实现过程:
使用pyecharts生成一个html文件,然后利用phantomjs无头浏览器打开页面执行操作,用法为:

cmd = ["phantomjs", genImgJs, outPutHtml, outPutImg]
try:
    subprocess.check_output(cmd, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as err:
    print err

关于那个作为参数的js文件:

"use strict";
var page = require('webpage').create(),
    system = require('system'),
    address, output, size, pageWidth, pageHeight;

if (system.args.length < 3 || system.args.length > 5) {
    console.log('Usage: rasterize.js URL filename [paperwidth*paperheight|paperformat] [zoom]');
    console.log('  paper (pdf output) examples: "5in*7.5in", "10cm*20cm", "A4", "Letter"');
    console.log('  image (png/jpg output) examples: "1920px" entire page, window width 1920px');
    console.log('                                   "800px*600px" window, clipped to 800x600');
    phantom.exit(1);
} else {
    address = system.args[1];
    output = system.args[2];
    page.viewportSize = { width: 500, height: 380 };
    if (system.args.length > 3 && system.args[2].substr(-4) === ".pdf") {
        size = system.args[3].split('*');
        page.paperSize = size.length === 2 ? { width: size[0], height: size[1], margin: '0px' }
                                           : { format: system.args[3], orientation: 'portrait', margin: '1cm' };
    } else if (system.args.length > 3 && system.args[3].substr(-2) === "px") {
        size = system.args[3].split('*');
        if (size.length === 2) {
            pageWidth = parseInt(size[0], 10);
            pageHeight = parseInt(size[1], 10);
            page.viewportSize = { width: pageWidth, height: pageHeight };
            page.clipRect = { top: 0, left: 0, width: pageWidth, height: pageHeight };
        } else {
            console.log("size:", system.args[3]);
            pageWidth = parseInt(system.args[3], 10);
            pageHeight = parseInt(pageWidth * 3/4, 10); // it's as good an assumption as any
            console.log ("pageHeight:",pageHeight);
            page.viewportSize = { width: pageWidth, height: pageHeight };
        }
    }
    if (system.args.length > 4) {
        page.zoomFactor = system.args[4];
    }
    page.open(address, function (status) {
        if (status !== 'success') {
            console.log('Unable to load the address!');
            phantom.exit(1);
        } else {
            window.setTimeout(function () {
                page.render(output);
                phantom.exit();
            }, 1200);
        }
    });
}

更为完整一点的后端代码(django框架内):

config = PyEchartsConfig(echarts_template_dir=STATIC_ROOT)
env = EchartsEnvironment(pyecharts_config=config)
tpl = env.get_template('chart_template.html')
html = tpl.render(line=line)
outHtml = '{}.html'.format(col)
outPutHtml = os.path.join(STATIC_ROOT, outHtml)
write_utf8_html_file(outPutHtml, html)
genImgJs = os.path.join(STATIC_ROOT, 'js/genImg.js')
imageName = 'images/{}.png'.format(title+col)
outPutImg = os.path.join(STATIC_ROOT,imageName )
cmd = ["phantomjs", genImgJs, outPutHtml, outPutImg]
try:
    subprocess.check_output(cmd, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as err:
    print err

猜你喜欢

转载自blog.csdn.net/lockey23/article/details/80160137
今日推荐