接触highcharts这个图表插件已经有好几年了,摸打滚爬到现在可以说对highchart已经有一定的了解了
首先 Highcharts 本身就提供了导出图片的功能,只需要在配置中增加相应的参数即可1
2
3
4
5navigation : {
	buttonOptions : {
		enabled : true
	}
}
设置完毕即可导出图片了,但是这种方式有个缺点,就是导出图片时会请求highchart官方的服务器生成图片,最后返回客户端给用户下载,我们可以在官方源码中看到这样一段代码:1
2
3
4
5
6defaultOptions.exporting = {
	//enabled: true,
	//filename: 'chart',
	type: 'image/png',
	url: 'http://export.highcharts.com/'
}
那如何请求自己的服务器生成对应的图片呢?官方API已经为我们留出了对应的接口供我们调用
点击这里可以查看exportChart相关属性
如何配置自己服务器的URL,有2种方式:
全局配置文件中配置
- 建立一个自己常用的 highchart配置文件 在配置属性中配置 exporting 的相关属性 
 大家可以新建一个通用js文件叫ChartOptions.js,将下面的代码拷入即可,代码中exporting 设置自己的服务器URL,contextButton 数组里可以扩展自己其他的按钮。- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124- function GetChartOptions() { 
 var options = {
 chart : {
 renderTo : '',
 // 是否开启水平缩放
 zoomType:null
 },
 loading : {
 hideDuration : 1000,
 showDuration : 1000
 },
 yAxis : {
 title : {
 text : ""
 },
 allowDecimals : false,
 min : 0,
 tickPixelInterval : 72
 },
 legend:{
 enabled:true
 },
 xAxis : {
 type : 'linear',
 categories:null,
 minRange:null,
 tickInterval:null,
 labels : {
 rotation : 0
 },
 },
 navigation : {
 buttonOptions : {
 enabled : true
 }
 },
 credits : {
 // 是否启用右下角水印
 enabled : false
 },
 plotOptions : {
 bar : {
 dataLabels : {
 enabled : true
 }
 },
 column : {
 cursor : 'pointer',
 depth : 25
 },
 pie : {
 allowPointSelect : true,
 cursor : 'pointer',
 dataLabels : {
 enabled : true,
 color : '#000000',
 connectorColor : '#000000',
 format : '<b>{point.name}</b>: {point.percentage:.1f} %'
 },
 showInLegend : true,
 events: {
 click:null
 }
 },
 line : {
 dataLabels : {
 enabled : false
 },
 cursor : 'pointer'
 },
 series:{
 pointStart : 0,
 pointInterval : 1,// 24 * 3600 * 1000
 point: {
 events: {
 click: null
 }
 }
 }
 },
 tooltip : {
 xDateFormat : '%Y-%m-%d'
 },
 subtitle : {
 text : ""
 },
 title : {
 text : ""
 },
 exporting: {
 buttons: {
 contextButton: {
 menuItems: [{
 text: '导出JPEG',
 onclick: function () {
 this.exportChart({
 type: 'image/jpeg'
 });
 }
 },
 {
 text: '导出PNG',
 onclick: function () {
 this.exportChart();
 }
 },
 {
 text: '导出PDF',
 onclick: function () {
 this.exportChart({
 type: 'application/pdf'
 });
 }
 }]
 }
 },
 width: '800',
 formAttributes: {"accept-charset":"utf-8"},
 url: "/exportSvg/convertSvg.html" //将此URL改成自己服务器请求URL即可
 },
 series : []
 };
 return options;
 }
- 接下来是调用初始化图表,highchart初始化也有2种方式,第一种是 jquery方式,第二种是原生的highchart方式,这里我介绍的是第二种方式,在前端放入一个DIV,ajax请求后在success中调用下面这段代码: - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27- var chart = null; 
 var option = GetChartOptions();
 // 这里为renderTo 赋值,要渲染的div ID名称
 option.chart.renderTo = "divForwardPersonRanking";
 option.chart.height = 350;
 option.chart.width=$("#divForwardPersonRanking").width();
 option.xAxis.labels.rotation = -45;
 option.title.text = "转发排行前十";
 var category = [];
 var obj = {
 name : "转发数",
 data : []
 }
 //这里的data 是ajax返回回来的数据
 if (!jQuery.isEmptyObject(data) && data.length > 0) {
 $.each(data, function(i, n) {
 category.push(n.userName);
 obj.data.push( [ n.userName, n.times ]);
 });
 option.xAxis.categories = category;
 }
 //这里是为series动态填充数据
 option.series.push(obj);
 //这里为图表指定类型
 option.chart.type = "column";
 //最后开始渲染
 chart = new Highcharts.Chart(option);
外部自定义DownLoad方法,用chart对象调用
注意 :这种方法和上面那种方法稍微有点区别,即我们可以把按钮放在图表外自己喜欢的任意位置,而第一种方式,只能通过highchart封装的按钮去导出图片,使用第二种方法前,先将上面highchart配置文件中的 exporting 节点去掉,因为我们会在外部通过chart对象调用export方法
- 前端HTML,这里我用span充当了一个按钮用来导出图片 - 1 
 2- <div id="div_img"></div> 
 <span class="section-buttons normal-button button-list" onclick="DownLoad()">导出数据</span>
- 前端js代码 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53- var chart; 
 function InitChart()
 {
 $.ajax({
 type: "GET",
 url: location.href + "?action=getChart",
 dataType: 'json',
 data: "AnalysisType=" + condition.TypeAnalysisA,
 beforeSend: function () {
 },
 success:function(result){
 if (!jQuery.isEmptyObject(result) && result.length > 0) {
 //chart参数设置
 var options = GetChartOptions();
 //接着对options的参数进行赋值
 option.chart.height = "300";
 option.chart.renderTo = "div_img";
 option.chart.width = "400";
 option.title.text="主标题";
 option.title.text="副标题";
 option.chart.type = "pie";//指定需要渲染的图表类型
 var obj = { name: "类型分布", data: [] };
 $.each(result, function (i, n) {
 var c = "";
 //根据不同的类型指定不同的颜色,当然也可以在后台json中拼好后前台直接使用
 switch (n.Name.toString()) {
 case "news": c = "#FFDBC4"; break;
 case "blogs": c = "#F2FAD7"; break;
 case "weibo": c = "#D3DCD0"; break;
 }
 var temp = { name: n.Name, y: parseInt(n.Values), color: c };
 obj.data.push(temp);
 });
 option.series.push(obj);
 chart = new Highcharts.Chart(option);
 }
 }
 });
 }
 function DownLoad()
 {
 if(chart!=null)
 {
 var currentDate = new Date();
 chart.exportChart({
 type: "image/jpeg",//指定导出的类型
 width: '800',
 url: location.href + "?action=export"
 filename: currentDate.getTime() //图片的名称,当然也可以在后台定义
 });
 }
 }
 InitChart();
说明:第二种方法,先初始化chart对象,然后在外部定义了一个DownLoad方法,用过span按钮去调用该方法,最后通过chart对象动态调用了exportChart方法
- 前端的代码的阐述到此结束,接下来为大家介绍下后端对应的代码(这里我只介绍asp.net的,其他语言可以在官网下载相关的代码)1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93private void ExportData() 
 {
 string tType = Request.Form["type"].ToString();
 string tSvg = Request.Form["svg"].ToString();
 string tFileName = Request.Form["filename"].ToString();
 if (tFileName == "")
 {
 tFileName = "chart";
 }
 MemoryStream tData = new MemoryStream(Encoding.UTF8.GetBytes(tSvg));
 MemoryStream tStream = new MemoryStream();
 string tTmp = new Random().Next().ToString();
 string tExt = string.Empty;
 string tTypeString = string.Empty;
 switch (tType)
 {
 case "image/png":
 tTypeString = "-m image/png";
 tExt = "png";
 break;
 case "image/jpeg":
 tTypeString = "-m image/jpeg";
 tExt = "jpg";
 break;
 case "application/pdf":
 tTypeString = "-m application/pdf";
 tExt = "pdf";
 break;
 case "image/svg+xml":
 tTypeString = "-m image/svg+xml";
 tExt = "svg";
 break;
 }
 
 if (!string.IsNullOrEmpty(tTypeString))
 {
 string tWidth = Request.Form["width"].ToString();
 Svg.SvgDocument tSvgObj = SvgDocument.Open(tData);
 switch (tExt)
 {
 case "jpg":
 tSvgObj.Draw().Save(tStream, ImageFormat.Jpeg);
 break;
 case "png":
 tSvgObj.Draw().Save(tStream, ImageFormat.Png);
 break;
 case "pdf":
 PdfWriter tWriter = null;
 Document tDocumentPdf = null;
 try
 {
 tSvgObj.Draw().Save(tStream, ImageFormat.Png);
 tDocumentPdf = new Document(new Rectangle((float)tSvgObj.Width, (float)tSvgObj.Height));
 tDocumentPdf.SetMargins(0.0f, 0.0f, 0.0f, 0.0f);
 iTextSharp.text.Image tGraph = iTextSharp.text.Image.GetInstance(tStream.ToArray());
 tGraph.ScaleToFit((float)tSvgObj.Width, (float)tSvgObj.Height);
 
 tStream = new MemoryStream();
 tWriter = PdfWriter.GetInstance(tDocumentPdf, tStream);
 tDocumentPdf.Open();
 tDocumentPdf.NewPage();
 tDocumentPdf.Add(tGraph);
 tDocumentPdf.CloseDocument();
 }
 catch (Exception ex)
 {
 throw ex;
 }
 finally
 {
 tDocumentPdf.Close();
 tDocumentPdf.Dispose();
 tWriter.Close();
 tWriter.Dispose();
 tData.Dispose();
 tData.Close();
 
 }
 break;
 
 case "svg":
 tStream = tData;
 break;
 }
 
 Response.ClearContent();
 Response.ClearHeaders();
 Response.ContentType = tType;
 Response.AppendHeader("Content-Disposition", "attachment; filename=" + tFileName + "." + tExt + "");
 Response.BinaryWrite(tStream.ToArray());
 Response.End();
 }
 }
总结:原理大概就是这样子的:
1、初始化图表
2、调用export方法请求服务器,export会获取到图表的svg信息,然后以post的方式将form提交给URL
3、后台接受到请求,获取相关的参数,调用图片处理程序绘制图片