接触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
124function 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
27var 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
53var 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、后台接受到请求,获取相关的参数,调用图片处理程序绘制图片