• phantomjs server + highchart 在服务器端生成highchart图表图片


    前言

    当项目需要将一个highchart图表以邮件发送的时候,js+css形式的highcharts 图表肯定是不好做的,有查可以借助flash去执行js,但很麻烦,所以折中将highchart图表转为图片。并且这个邮件里可能有几十个这样的图表,在浏览器端生成图片再上传发送的方案也不可取,所以选择直接在服务端生成highchart图表。

    服务端图表其实也有PChart之类的直接在服务端生成图片的,不过那图片效果实在不敢恭维。最后找到了phantomjs+highchart的方式生成highchart图表,图表美观。

    参考: http://www.highcharts.com/articles/2-news/56-improved-image-export-with-phantomjs

    phantomjs  是一个服务端JavaScript执行引擎。

    phantomjs + highchart支持两种方式,一种是命令行方式,一种是server方式。在使用命令行方式造成进程数过多把服务器整挂一次后,我换成了phantomjs Server的方式,这种方式效果好,所以下面的示例也使用的是phantomjs server

    安装phantomjs

    可以编译安装也可以直接下载rpm,或者下载已经静态编译可以直接执行的二进制文件。这三者我都做过,最后因为要安装的机器比较多,每台机器还有点区别,有的编译成功有的编译失败,最后懒惰的我直接找到了可以直接下载使用的phantomjs二进制可执行文件。

    https://bitbucket.org/ariya/phantomjs/downloads 直接下载二进制文件(我现在的环境打不开这个页面了,估计要翻墙)

    安装完之后,在demo根目录下行执行以下命令启动phantomjs server

    phantomjs highcharts-convert.js -host 127.0.0.1 -port 3003

    其中demo目录下有这些文件,其中highcharts-convert.js文件能够使用的网上已经非常难找了,需要的可以联系我。

    highcharts-convert.js  highcharts.js  highcharts-more.js  highstock.js  jquery-1.8.3.min.js  loadspeed.js   rasterize.js

    DEMO

    下面编写测试代码

     1 <?php
     2 
     3 $options = array('chart' => array('type' => 'spline', 'width' => '500', 'height' => '300', 'style' => array('fontFamily' => 'consolas,Console,SimSun'), 'backgroundColor' => '#F5F8F9'), 'tooltip' => array('valueSuffix' => '%'), 'colors' => array('#3366CC', '#097138', '#AB0'), 'credits' => array('enabled' => 0), 'yAxis' => array('title' => array('text' => '百分比(%)'), 'plotLines' => array(0 => array('value' => 0, 'width' => 1, 'color' => '#808080'))), 'title' => array('text' => '视频下载成功率3G'), 'xAxis' => array('categories' => array('1-22', '1-23', '1-24', '1-25', '1-26', '1-27', '1-28')), 'series' => array(0 => array('name' => 'Android版(6.0 正式)6.0.1.288', 'data' => array(0, 100, 100, 0, 0, 100, 0)), 1 => array('name' => 'Android版(5.8正式)5.8.1.288', 'data' => array(96.75, 96.90000000000001, 89.3, 81.16, 97.23, 92.59, 98.73999999999999)), 2 => array('name' => 'Android版(5.7正式换包)5.7.1.289', 'data' => array(96.55, 25, 91.08, 100, 100, 0, 97.14))));
     4 
     5 
     6 $optionsJson = json_encode($options);
     7 $imgFile = dirname(__FILE__) . '/' . md5($optionsJson) . '.png';
     8 $curl = curl_init('127.0.0.1:3003');
     9 curl_setopt($curl, CURLOPT_POST, true);
    10 curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    11 $postData = json_encode(array(
    12     'infile'  => preg_replace('/"(w+)":/', '${1}:', $optionsJson),
    13     'outfile' => $imgFile,
    14 ));
    15 curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
    16 $resp = curl_exec($curl);

    参数细节

    请注意上面的

    1 $postData = json_encode(array(
    2     'infile'    =>  preg_replace('/"(w+)":/','${1}:',$optionsJson),
    3     'outfile'   =>  $imgFile
    4 ));

    第2行中的infile为什么要这么写呢?因为传递给highchart-convert.js的infile需要的参数,并不是标准的json,这个不仔细看真注意不到。

    可以仔细看 http://www.highcharts.com/articles/2-news/56-improved-image-export-with-phantomjs 参数说明

    "{"infile":"{xAxis: {categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']},series: [{data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]}]};","callback":"function(chart) {chart.renderer.arc(200, 150, 100, 50, -Math.PI, 0).attr({fill : '#FCFFC5',stroke : 'black','stroke-width' : 1}).add();}","constr":"Chart","outfile":"//tmp//chart.png"}"

    可以上面红色的代码,并不是json而是js对象格式。

    上面有preg_replace替换的php代码得到的是就是这样的json

    {"infile":"{chart:{type:"spline","500",height:"300",style:{fontFamily:"consolas,Console,SimSun"},backgroundColor:"#F5F8F9"},tooltip:{valueSuffix:"%"},colors:["#3366CC","#097138","#AB0"],credits:{enabled:0},yAxis:{title:{text:"\u767e\u5206\u6bd4\uff08%\uff09"},plotLines:[{value:0,1,color:"#808080"}]},title:{text:"\u89c6\u9891\u4e0b\u8f7d\u6210\u529f\u73873G"},xAxis:{categories:["1-22","1-23","1-24","1-25","1-26","1-27","1-28"]},series:[{name:"Android\u7248(6.0 \u6b63\u5f0f)6.0.1.288",data:[0,100,100,0,0,100,0]},{name:"Android\u7248(5.8\u6b63\u5f0f)5.8.1.288",data:[96.75,96.9,89.3,81.16,97.23,92.59,98.74]},{name:"Android\u7248(5.7\u6b63\u5f0f\u6362\u5305)5.7.1.289",data:[96.55,25,91.08,100,100,0,97.14]}]}","outfile":"/home/wwwroot/demo.qq.com/25afeab1d3e957b8beb4c58ea79c6ebd.png"}

    转成js对象可以看到是这样的

    如果不像上面那样写,而是直接写成

    1 $postData = json_encode(array(
    2     'infile'    =>  $options,
    3     'outfile'   =>  $imgFile
    4 ));

    得到的json是这样的

    {"infile":{"chart":{"type":"spline","width":"500","height":"300","style":{"fontFamily":"consolas,Console,SimSun"},"backgroundColor":"#F5F8F9"},"tooltip":{"valueSuffix":"%"},"colors":["#3366CC","#097138","#AB0"],"credits":{"enabled":0},"yAxis":{"title":{"text":"u767eu5206u6bd4uff08%uff09"},"plotLines":[{"value":0,"width":1,"color":"#808080"}]},"title":{"text":"u89c6u9891u4e0bu8f7du6210u529fu73873G"},"xAxis":{"categories":["1-22","1-23","1-24","1-25","1-26","1-27","1-28"]},"series":[{"name":"Androidu7248(6.0 u6b63u5f0f)6.0.1.288","data":[0,100,100,0,0,100,0]},{"name":"Androidu7248(5.8u6b63u5f0f)5.8.1.288","data":[96.75,96.9,89.3,81.16,97.23,92.59,98.74]},{"name":"Androidu7248(5.7u6b63u5f0fu6362u5305)5.7.1.289","data":[96.55,25,91.08,100,100,0,97.14]}]},"outfile":"/home/wwwroot/demo.qq.com/25afeab1d3e957b8beb4c58ea79c6ebd.png"}

    换成js对象是这样的

    而且请求发送给phantomjs执行会出错

    这是一个坑

    输出

    如果参数不指定outfile,那么curl_exec 得到的响应resp就是图片数据的base64编码数据。可以直接decode输出

    乱码问题

    另外,服务器端生成图表,一定要为Linux安装bitmap字体,否则会得到下面这样的乱码图片

    安装的方式很简单

    yum install bitmap-fonts bitmap-fonts-cjk

    然后就能得到正常的图表了

    另外再给系统安装一些其余漂亮的中文字体,在highchart中可以指定中文字体,让图表更加漂亮。

    注:因为写博客的时间与做这个事情的时间相距较远,输出的图片与代码数据并不匹配,见谅。

  • 相关阅读:
    C/S 与 B/S 区别
    XE2的一些新东西
    Versant数据库实验
    概率算法sherwood算法
    组合数学引论部分习题答案
    概率算法n皇后的LV算法
    概率算法Las Vegas
    小型企业库存管理系统的设计与实现
    概率算法Numerical和Monte Carlo
    我的彩票梦十一运夺金模拟程序
  • 原文地址:https://www.cnblogs.com/lvyahui/p/5428246.html
Copyright © 2020-2023  润新知