HighCharts使用笔记
HighChars官网地址:http://www.highcharts.com/products/highcharts/ 中文网地址:http://www.hcharts.cn/index.php
官方介绍:
WHAT IS HIGHCHARTS?
Highcharts is a charting library written in pure JavaScript, offering an easy way of adding interactive charts to your web site or web application. Highcharts currently supports line, spline, area, areaspline, column, bar, pie, scatter, angular gauges, arearange, areasplinerange, columnrange, bubble, box plot, error bars, funnel, waterfall and polar chart types.
其实HighCharts就是一个
功能强大、开源、美观、图表丰富、兼容绝大多数浏览器的纯js图表库
主要特点:
- 兼容 IE6+ 等主流浏览器,完美支持移动端手势、缩放操作
- 强大的交互性:数据标签、数据提示框、隐藏与显示、动态更新
- 图表类型丰富,支持多达 20 种图表,并且可以混合使用
- 简单易用,文档丰富详细
以上都是官网的介绍,下面进入正题,最近在研究HighCharts,虽然上手很容易功能很强大,但是还是遇到一些问题,下面记录以下,以便有需要的人参考:
准备工作:在官网下载相关js文件,需要引入的js (jquery版本当然越高越好):
<script src="~/Scripts/jquery-1.8.2.min.js"></script> <script src="~/Scripts/highchart/highcharts.js"></script> <script src="~/Scripts/highchart/modules/exporting.js"></script>
1.静态数据:
这个比较简单,按着官方demo很容易就可以出来,下面以柱状图为例:
$(function () { $('#container').highcharts({ chart: { type: 'column', margin: [ 50, 50, 100, 80] }, title: { text: 'Worlds largest cities per 2008' }, xAxis: { categories: [ 'Tokyo', 'Jakarta', 'New York', 'Seoul', 'Manila', 'Mumbai', 'Sao Paulo', 'Mexico City', 'Dehli', 'Osaka', 'Cairo', 'Kolkata', 'Los Angeles', 'Shanghai', 'Moscow', 'Beijing', 'Buenos Aires', 'Guangzhou', 'Shenzhen', 'Istanbul' ], labels: { rotation: -45, align: 'right', style: { fontSize: '13px', fontFamily: 'Verdana, sans-serif' } } }, yAxis: { min: 0, title: { text: 'Population (millions)' } }, legend: { enabled: false }, tooltip: { pointFormat: 'Population in 2008: <b>{point.y:.1f} millions</b>', }, series: [{ name: 'Population', data: [34.4, 21.8, 20.1, 20, 19.6, 19.5, 19.1, 18.4, 18, 17.3, 16.8, 15, 14.7, 14.5, 13.3, 12.8, 12.4, 11.8, 11.7, 11.2], dataLabels: { enabled: true, rotation: -90, color: '#FFFFFF', align: 'right', x: 4, y: 10, style: { fontSize: '13px', fontFamily: 'Verdana, sans-serif', textShadow: '0 0 3px black' } } }] }); });
//页面只需要放上一个div来展示图表
<div id="container" style="width:100%; height: 100%; margin: 0 auto"></div>
按照上面的代码,就可以看到效果了,效果很漂亮:
几个主要的属性做一下介绍,其它属性可以查看官网API,讲的都比较详细:
type: 'column', 类型是柱状图,也可以换成line (拆线图)
categories:{} X轴坐标
series: [{ name: 'Population', data:[1,20,40,50,60] }]
数据列中的 name 代表数据列的名字,并且会显示在数据提示框(Tooltip)及图例(Legend)中; 在数据列的 data 属性中,我们可以定义图表的数据数组,通常有三种定义方式: 1、数值数组。在这种情况下,配置数组中的数值代表 Y 值,X 值则根据 X 轴的配置,要么自动计算,要么从 0 起自增,或者是根据 pointStart 及 pointInterval 自增;在分类轴中, X 值就是 categoies 配置,数值数组配置实例如下: data : [1, 4, 6, 9, 10] 2、包含两个值的数组集合。在这种情况下,集合中数组的第一个值代表 X, 第二个值代表 Y;如果第一个值是字符串,则代表该点的名字,并且 X 值会如 1 中所说的情况决定。数组集合的实例: data : [ [5, 2], [6,3], [8,2] ] 3、数据点对象集合。在这种情况下,集合中元素都是数据点对象,对象中可以配置数据见 plotOptions.series 或 plotOptions.{图表类型} 所列。配置实例: data : [{ name : "point 1", color : "#00ff00", y : 0 }, { name : "Point 2", color : "#ff00ff", y : 5 }]
2.动态数据:
在实际使用中,我们通常是使用动态数据,以MVC项目为例,通过ajax请求,由controller返回给前台相应的json数据,前台解析后绘制图表,比如我们要统计出来一个月内的消费情况,我们的费用支出有吃饭、水电费、其它支出:
Controller代码:
/// <summary> /// 得到当月的数据 /// </summary> /// <returns></returns> public ActionResult GetCurrentMonthData() { DateTime now = DateTime.Now; var dataList = from dic in db.FundDic join s in db.Statement.Where(a=> SqlMethods.DateDiffMonth(a.OccurTime, now) == 0) on dic.ID equals s.ItemID into temp from tt in temp.DefaultIfEmpty() where dic.Type == 2//表示支出的费用 group tt by dic.Item into g select new { ItemName = g.Key, Money = g.Sum(tt => tt.Money) ==null?0:g.Sum(tt => tt.Money)//按支出项统计总金额 }; var jsonData = Newtonsoft.Json.JsonConvert.SerializeObject(dataList); return Content(jsonData); }
Html页代码:
<script type="text/javascript"> $(function () { var xtext = [];//X轴TEXT var ytext = [];//Y值 $.ajax({ type: "GET", url: "/MyBank/GetCurrentMonthData", dataType: "json", data: "userName=aaa",//根据需要可传一些参数 beforeSend: function (XMLHttpRequest) { }, success: function (msg) { for(var i=0;i<msg.length;i++) { ytext[i] = msg[i].Money;//Y轴 xtext[i] = msg[i].ItemName;//X轴 } var chart = new Highcharts.Chart({ chart: { renderTo: 'container', type: 'column', margin: [50, 50, 100, 80] }, title: { text: '月消费详细' }, xAxis: { categories: xtext, labels: { rotation: -45, align: 'right', style: { fontSize: '13px', fontFamily: 'Verdana, sans-serif' } } }, yAxis: { min: 0, title: { text: '花费 (¥)' } }, legend: { enabled: false }, tooltip: { headerFormat: '<span style="font-size:10px">{point.key}</span><table>', pointFormat: '本月支出: <b>{point.y:.1f} 元</b>' }, series: [{ name: 'Tokyo', data: ytext, dataLabels: { enabled: true, rotation: -90, color: '#FFFFFF', align: 'right', x: 4, y: -20, style: { fontSize: '13px', fontFamily: 'Verdana, sans-serif', textShadow: '0 0 3px black' } } }] }); }, complete: function (XMLHttpRequest, textStatus) { //隐藏正在查询图片 }, error: function () { //错误处理 } }); }); </script> <div id="container" style="width:100%; height: 100%; margin: 0 auto"></div>
也很简单,只需要返回json数据,然后解析后赋给x轴和y轴即可;
3.动态数据,且是多维数组:
上图返回的是当月的数据,我们返回的数据格式是 [{ItemName:解决温饱, Money:280},{ItemName:其它乱七八糟, Money:200},{ItemName:水/电/燃气, Money:0}],
如果我们需要返回2014年和2015年的每月消费情况,json数据如下,我们需要展示两张折线图来比较两年的费用支出情况:
[{"Year": 2015,
"Data": [{"Month": 1,"Money": 150},{"Month": 2,"Money": 50},{"Month": 3,"Money": 2000},{"Month": 4,"Money": 5000},{"Month": 5,"Money": 3500},{"Month": 6,"Money": 0},
{"Month": 7,"Money": 4800},{"Month": 8,"Money": 6000},{"Month": 9,"Money": 1200},{"Month": 10, "Money": 800},{"Month": 11,"Money": 650},{"Month": 12,"Money": 2100}]}, { "Year": 2014,
"Data": [{"Month": 1,"Money": 2000},{"Month": 2,"Money": 3000},{"Month": 3,"Money": 1500},{"Month": 4,"Money": 100},{"Month": 5,"Money": 1800},{"Month": 6,"Money": 3500},
{"Month": 7,"Money": 200},{"Month": 8,"Money": 5600},{"Money": 2000},{"Month": 10, "Money": 4000},{"Month": 11,"Money": 3000},{"Month": 12,"Money": 500}]}]
基本上跟2中的方法,返回这样的json数据后,多循环一次,将Data中的数据赋给Y轴,但是需要声明两个series,series[0],series[1]
Cotroller代码:
//每月支出 public ActionResult GetExpenditureByMonth() { string year = Request["year"] ?? DateTime.Now.Year.ToString(); var dataList = (from t in db.Statement where t.Type == 2 group t by new { t.OccurTime.Value.Year,t.OccurTime.Value.Month} into g select new Expenditure { Month=g.Key.Month, Money=g.Sum(t=>t.Money) }).ToList(); IEnumerable<IGrouping<int, Expenditure>> groupList = dataList.GroupBy(e => e.Year);//按年份分组 jsonData = Newtonsoft.Json.JsonConvert.SerializeObject(groupList);
return Content(jsonData);
}
Html代码:
<script type="text/javascript">
$(function () { $.ajax({ type: "post", dataType: "json", data: { "year": "2015" }, //参数列表 async: false, url: "/MyBank/GetExpenditureByMonth", success: function (result) { var jsonData = result; for (var i = 0; i < jsonData.length; i++) { var data=[];for (var j = 0; j < jsonData[i].Data.length; j++) { data[j]=jsonData[i].Data.Money; }options.series[i].name = jsonData[i].Year; options.series[i].data = data; } var tiltleTm = "Title"; //tiltleTm 是后台传向前台的参数,代表图标的标题 var chart = new Highcharts.Chart({ chart: { renderTo: 'container', //要显示柱状图的div的id type: 'line', //图表类型为柱状图 margin: 75, options3d: { //这里设置3D图表的样式 enabled: true, alpha: 10, beta: 0, depth: 50, viewDistance: 25 } }, title: { text: tiltleTm //显示柱状图的标题 }, credits: {//不显示highchart超链接 enabled: false }, plotOptions: { column: { depth: 10, value: 0, width: 1 } }, yAxis: { //纵坐标 title: { text: '单位:元' } }, xAxis: { //横坐标 categories: [1,2,3,4,5,6,7,8,9,10,11,12] }, tooltip: { //提示格式 shared: true, useHTML: true, headerFormat: '<small>{point.key}</small><table>', pointFormat: '<tr><td style="color: {series.color}">{series.name}: </td>' + '<td style="text-align: right"><b>{point.y} 元</b></td></tr>', footerFormat: '</table>', valueDecimals: 2 }, series: [{ name: '支出' },{ name: '支出' }] }); }, error: function () { alert('获取失败!'); } }); }); </script>
这样出来的效果是:
效果虽然出来了,但是有点不爽的地方不知道大家有没有发现,
series: [{ name: '支出' },{ name: '支出' }]
我们要显示两个数组,这块就得定义两个name,如果只定义一个的话,循环到第二遍时,这里会报错,
options.series[i].name = jsonData[i].Year; options.series[i].data = data;
如果我们要返回5个数组,我们还得写5遍这里,这我们怎么可以忍,baidu了一些资料后,看到一个方法,先定义多个name,要比我们返回的数组个数多,然后循环赋值,完事后再把多余的删掉,虽然可行,但是处女座的程序猿怎么可以忍,于是又继续baidu,功夫不负有心人,
终于发现一个靠谱的方法,series其实是个数组,我们只需要组织好数组数据然后赋给series即可:
//定义基本属性 var options = { credits: //HighCharts如何去除图表右下角的highcharts.com链接 { enabled: true, href: "http://www.52wulian.org", text: "浏览总量:291,IP总数:74 – 我爱物联网" }, chart: { renderTo: 'container', //要显示柱状图的div的id type: 'line', //图表类型为柱状图 margin: 75, options3d: { //这里设置3D图表的样式 enabled: true, alpha: 10, beta: 0, depth: 50, viewDistance: 25 } }, title: { text: 'My first Highcharts chart', //指定图表标题 align: 'center' }, tooltip: { //提示格式 shared: true, useHTML: true, headerFormat: '<small>{point.key}</small><table>', pointFormat: '<tr><td style="color: {series.color}">{series.name}: </td>' + '<td style="text-align: right"><b>{point.y} 元</b></td></tr>', footerFormat: '</table>', valueDecimals: 2 }, subtitle: { useHTML: true, text: "Highcharts中文网 | <a href='http://www.hcharts.cn' target='_blank'>中文教程</a>" }, xAxis: { }, yAxis: { title: { text: '单位:元' //指定y轴的标题 } }, series: [], };
然后在取得数据后再将options赋给HighChart
var mySeries = new Array(jsonData.length); for (var i = 0; i < jsonData.length; i++) { datas[i]=new Array(); for (var j = 0; j < jsonData[i].Data.length; j++) { datas[i].push(jsonData[i].Data[j].Money); } mySeries[i]={ "name": jsonData[i].Year,data:datas[i] }; } options.series = mySeries; options.xAxis.categories = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
另外:如果要做气泡图,需要引入脚本 <script src="~/Scripts/highchart/highcharts-more.js"></script>
以上是本人在使用HighCharts时遇到的一些问题,代码肯定有不妥之处,欢迎拍砖!