前言:
2012年從長沙跑到深圳,2016年又從深圳回到長沙,兜兜轉(zhuǎn)轉(zhuǎn)一圈,又回到了原點.4年在深圳就呆了一家公司,回長沙也是因為深圳公司無力為繼,長沙股東老板挽留,想想自己年紀(jì)也不小了.就回來了,在長沙工作幾月,也沒什么太多的不適應(yīng).不用趕著項目上線,不用加班,想想其實也不錯.
從12年在長沙就想寫點開源的東西,不過實在不敢獻(xiàn)丑.這次機緣巧合,有個朋友一個項目需要用到大量報表,我找到百度的開源echarts項目(感謝開源,4年工作以來用到很多很好的開源項目,對工作助力頗多),看著就挺舒服的,又看到了@abel533寫的java類庫,萌生了想寫一個.net類庫的想法.項目后來沒做下去了,但是echart類庫倒是堅持寫下來了.?dāng)鄶嗬m(xù)續(xù)幾個月的時間,終于有點樣子了.之所以寫這篇博客,是因為最近在園子里看到很多看衰.net的文章,我無法判斷對錯,也不想引起爭論,不過我只是簡單喜歡編程的人,能夠做自己喜歡的事就好,其實好的環(huán)境需要大家一起營造,我也想為.net陣營做一些有意義的事情.
源碼:
源碼地址:https://github.com/idoku/EChartsSDK
示例地址:http://echarts./
echart地址:http://echarts.baidu.com/
先放幾張eharts的圖感受一下:

折線圖

柱狀圖

散點圖

餅圖
正文
ECharts .Net類庫
當(dāng)前版本1.0.1
Echarts
本項目是一個供.NET開發(fā)者使用的ECharts的開發(fā)包,主要目的是方便在.NET中構(gòu)件Echarts中可能用的全部數(shù)據(jù)結(jié)構(gòu),完整的Option結(jié)構(gòu). ChartOption中的數(shù)據(jù)Series,包含Line-折線圖,Bar-柱狀圖,Pie-餅圖,Scatter-散點圖等,支持Echarts中所有圖表.支持所有Style類,如AreaStyle,ItemStyle,LineStyle等.支持多種Data數(shù)據(jù)類型,一個通用的Data數(shù)據(jù),以及PieData,PolarData,TreeData等個性化數(shù)據(jù)結(jié)構(gòu).
你可以使用本項目直接構(gòu)件一個Option對象,使用方法JsonTools.ObjectToJson2(option),(直接使用Json方式返回存在問題,因為function不是標(biāo)準(zhǔn)化的json格式,轉(zhuǎn)換會報錯).
圖表類型
- Line - 折線(面積)圖
- Bar - 柱狀(條形)圖
- Scatter - 散點(氣泡)圖
- K - K線圖
- Pie - 餅(圓環(huán))圖
- Radar - 雷達(dá)(面積)圖
- Chord - 和弦圖
- Force - 力導(dǎo)向布局圖
- Map - 地圖
- Gauge - 儀表盤
- Funnel - 漏斗圖
- Heatmap - 熱力圖
- EventRiver - 事件河流圖
- Venn - 韋恩圖
- Tree - 樹圖
- Treemap - 矩形樹圖
- WordCloud - 詞云
Echarts組件
- Axis - 坐標(biāo)軸
- Grid - 網(wǎng)格
- Title - 標(biāo)題
- Tooltip - 提示
- Legend - 圖例
- DataZoom - 數(shù)據(jù)區(qū)域縮放
- DataRange - 值域漫游
- Toolbox - 工具箱
- Timeline - 時間線
ChartOption說明
- ChartOption 是echarts的主要類.
- 使用JsonTools.ObjectToJson2方法返回給前端時,需要使用eval('(' + data + ')')轉(zhuǎn)換為JSON結(jié)構(gòu).
Function說明
由于json標(biāo)準(zhǔn)中不包含function類型,一般json庫都不支持這種類型,處理這種類型最簡單的方式是轉(zhuǎn)換json字符串時,對字符串進(jìn)行處理.
讀者可以自行使用其他自定義方式實現(xiàn),本項目使用的.net自帶的JRaw()方式.不管是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | "formatter" : function( params ) {
// for text color
var color = colorList[ params [0].dataIndex];
var res = '<div style="color:' + color + '">' ;
res += '<strong>' + params [0].name + '消費(元)</strong>'
for ( var i = 0, l = params .length; i < l; i++) {
res += '<br/>' + params [i].seriesName + ' : ' + params [i].value
}
res += '</div>' ;
return res;
},
|
和
"color": (function (){
var zrColor = require('zrender/tool/color');
return zrColor.getLinearGradient(
0, 400, 0, 300,
[[0, 'green'],[1, 'yellow']]
)
})(),
都可以利用JRaw來實現(xiàn).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | option.ToolTip().Trigger(TriggerType.axis)
.BackgroundColor( "rgba(255,255,255,0.7)" )
.Formatter( new JRaw( @"function(params) {
// for text color
var color = colorList[params[0].dataIndex];
var res = '<div style=""color:' + color + '"">';
res += '<strong>' + params[0].name + '消費(元)</strong>'
for (var i = 0, l = params.length; i < l; i++) {
res += '<br/>' + params[i].seriesName + ' : ' + params[i].value
}
res += '</div>';
return res;
}" ))
style.Emphasis().BarBorderColor( "green" ).BarBorderWidth(5)
.Color( new JRaw( @"(function (){
var zrColor = require('zrender/tool/color');
return zrColor.getLinearGradient(
0, 400, 0, 300,
[[0, 'red'],[1, 'orange']]
)
})()" ))
|
EchartsWeb
本項目通過ASP.NET MVC和ASP.NET web api模擬了echarts官網(wǎng)網(wǎng)站中的全部示例,主要目的是方便大家參考使用和調(diào)整結(jié)構(gòu).
地址:http://echarts./
1.簡單Line示例
演示地址: http://echarts./home/example?api=line1
例子中給出的json結(jié)構(gòu).
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 | {
"calculable" : true ,
"title" : {
"text" : "未來一周天氣變化" ,
"subtext" : "純虛構(gòu)數(shù)據(jù)" ,
"show" : true
},
"tooltip" : {
"trigger" : "axis"
},
"legend" : {
"data" : [
"最高溫度" ,
"最低溫度"
]
},
"xAxis" : [
{
"data" : [
"周一" ,
"周二" ,
"周三" ,
"周四" ,
"周五" ,
"周六" ,
"周日"
],
"boundaryGap" : false ,
"type" : "category"
}
],
"yAxis" : [
{
"type" : "value" ,
"axisLabel" : {
"formatter" : "{value} ℃"
}
}
],
"series" : [
{
"data" : [
13,
10,
12,
10,
13,
13,
14
],
"type" : "line" ,
"name" : "最高溫度" ,
"markPoint" : {
"data" : [
{
"name" : "最大值" ,
"type" : "max"
},
{
"name" : "最小值" ,
"type" : "min"
}
]
},
"markLine" : {
"data" : [
{
"name" : "平均值" ,
"type" : "average"
}
]
}
},
{
"data" : [
3,
-1,
1,
-1,
3,
3,
4
],
"type" : "line" ,
"name" : "最低溫度" ,
"markPoint" : {
"data" : [
{
"name" : "周最低" ,
"value" : -1,
"xAxis" : 1,
"yAxis" : -0.5
}
]
},
"markLine" : {
"data" : [
{
"name" : "平均值" ,
"type" : "average"
}
]
}
}
]
}
|
對應(yīng)的源碼:
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 | [AcceptVerbs( "GET" , "POST" )]
[ActionName( "line1" )]
public string StdLine()
{
IList< string > weeks = ChartsUtil.Weeks();
IList< int > datas1 = ChartsUtil.Datas(7, 10, 15);
IList< int > datas2 = ChartsUtil.Datas(7, -2, 5);
int min = datas2.Min();
int index = datas2.IndexOf(min);
ChartOption option = new ChartOption();
option.title = new Title()
{
show = true ,
text = "未來一周天氣變化" ,
subtext = "純虛構(gòu)數(shù)據(jù)"
};
option.tooltip = new ToolTip()
{
trigger = TriggerType.axis
};
option.legend = new Legend()
{
data = new List< object >(){
"最高溫度" ,
"最低溫度"
}
};
option.calculable = true ;
option.xAxis = new List<Axis>()
{
new CategoryAxis()
{
type = AxisType.category,
boundaryGap= false ,
data = new List< object >(weeks)
}
};
option.yAxis = new List<Axis>()
{
new ValueAxis()
{
type = AxisType.value,
axisLabel = new AxisLabel(){
formatter= new JRaw( "{value} ℃" ).ToString()
}
}
};
option.series = new List< object >()
{
new Line()
{
name = "最高溫度" ,
type = ChartType.line,
data = datas1,
markPoint = new MarkPoint()
{
data = new List< object >()
{
new MarkData()
{
name = "最大值" ,
type= MarkType.max,
},
new MarkData()
{
name = "最小值" ,
type= MarkType.min,
}
}
},
markLine = new MarkLine()
{
data = new List< object >()
{
new MarkData()
{
name = "平均值" ,
type = MarkType.average
}
}
}
},
new Line(){
name= "最低溫度" ,
type = ChartType.line,
data = datas2,
markPoint= new MarkPoint(){
data = new List< object >(){
new MarkData(){
name= "周最低" ,
value = min,
xAxis = index,
yAxis = min+0.5,
}
}
},
markLine = new MarkLine(){
data = new List< object >(){
new MarkData(){
type = MarkType.average,
name = "平均值"
}
}
}
}
};
var result = JsonTools.ObjectToJson2(option);
return result;
}
|
2.使用function的bar示例.
演示地址: http://echarts./home/example?api=bar10#
給出的json代碼:
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 125 126 127 128 129 130 | {
"title" : {
"text" : "溫度計式圖表" ,
"subtext" : "Form ExcelHome" ,
"feature" : {
"mark" : {
"show" : true
},
"dataView" : {
"show" : true ,
"readOnly" : false
},
"restore" : {
"show" : true
},
"saveAsImage" : {
"show" : true
}
},
"show" : true
},
"tooltip" : {
"trigger" : "axis" ,
"formatter" : function ( params ){
return params [0].name + '<br/>'
+ params [0].seriesName + ' : ' + params [0].value + '<br/>'
+ params [1].seriesName + ' : ' + ( params [1].value + params [0].value);
},
"axisPointer" : {
"type" : "shadow"
}
},
"legend" : {
"data" : [
"Acutal" ,
"Forecast"
]
},
"grid" : {
"y2" : 30,
"y" : 80
},
"xAxis" : [
{
"data" : [
"Cosco" ,
"CMA" ,
"APL" ,
"OOCL" ,
"Wanhai" ,
"Zim"
],
"type" : "category"
}
],
"yAxis" : [
{
"boundaryGap" : [
0.0,
0.1
],
"type" : "value"
}
],
"series" : [
{
"stack" : "sum" ,
"data" : [
260,
200,
220,
120,
100,
80
],
"type" : "bar" ,
"name" : "Acutal" ,
"itemStyle" : {
"normal" : {
"color" : "tomato" ,
"barBorderColor" : "tomato" ,
"barBorderRadius" : 0,
"barBorderWidth" : 6,
"label" : {
"show" : true ,
"position" : "insideTop"
}
}
}
},
{
"stack" : "sum" ,
"data" : [
40,
80,
50,
80,
80,
70
],
"type" : "bar" ,
"name" : "Forecast" ,
"itemStyle" : {
"normal" : {
"color" : "#fff" ,
"barBorderColor" : "tomato" ,
"barBorderRadius" : 0,
"barBorderWidth" : 6,
"label" : {
"show" : true ,
"position" : "top" ,
"formatter" : function ( params ) {
for ( var i = 0, l = option.xAxis[0].data.length; i < l; i++) {
if (option.xAxis[0].data[i] == params .name) {
return option.series[0].data[i] + params .value;
}
}
},
"textStyle" : {
"color" : "tomato"
}
}
}
}
}
]
}
|
對應(yīng)的源碼:
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 | [AcceptVerbs( "GET" , "POST" )]
[ActionName( "bar10" )]
public string TemperatureBar()
{
ChartOption option = new ChartOption();
option.Title().Text( "溫度計式圖表" ).Subtext( "Form ExcelHome" ).
option.ToolTip().Trigger(TriggerType.axis)
.Formatter( new JRaw( @"function (params){
return params[0].name + '<br/>'
+ params[0].seriesName + ' : ' + params[0].value + '<br/>'
+ params[1].seriesName + ' : ' + (params[1].value + params[0].value);
}" ))
.AxisPointer().Type(AxisPointType.shadow);
option.Legend().Data( "Acutal" , "Forecast" );
Feature feature = new Feature();
feature.Mark().Show( true );
feature.DataView().Show( true ).ReadOnly( false );
feature.Restore().Show( true );
feature.SaveAsImage().Show( true );
option.ToolBox().Show( true ).SetFeature(feature);
option.Grid().Y(80).Y2(30);
CategoryAxis x = new CategoryAxis();
x.Data( "Cosco" , "CMA" , "APL" , "OOCL" , "Wanhai" , "Zim" );
option.XAxis(x);
ValueAxis y = new ValueAxis();
y.BoundaryGap( new List< double >() { 0,0.1 });
option.YAxis(y);
var tomatoStyle = new ItemStyle();
tomatoStyle.Normal().Color( "tomato" ).BarBorderRadius(0)
.BarBorderColor( "tomato" ).BarBorderWidth(6)
.Label().Show( true ).Position(StyleLabelTyle.insideTop);
Bar b1 = new Bar( "Acutal" );
b1.Stack( "sum" );
b1.SetItemStyle(tomatoStyle);
b1.Data(260, 200, 220, 120, 100, 80);
var forecastStyle = new ItemStyle();
forecastStyle.Normal().Color( "#fff" ).BarBorderRadius(0)
.BarBorderColor( "tomato" ).BarBorderWidth(6)
.Label().Show( true ).Position(StyleLabelTyle.top)
.Formatter( new JRaw( @"function (params) {
for (var i = 0, l = option.xAxis[0].data.length; i < l; i++) {
if (option.xAxis[0].data[i] == params.name) {
return option.series[0].data[i] + params.value;
}
}
}" ))
.TextStyle().Color( "tomato" );
Bar b2 = new Bar( "Forecast" );
b2.Stack( "sum" );
b2.SetItemStyle(forecastStyle);
b2.Data(40, 80, 50, 80, 80, 70);
option.Series(b1, b2);
var result = JsonTools.ObjectToJson2(option);
return result;
}
|
博客總結(jié):
排版真是硬傷~~~因為在項目期間,百度將echarts版本升級到了3.0,但是我已經(jīng)實現(xiàn)了一半,所以就沒有使用新的3.0來實現(xiàn).而且上面說到的項目沒有做下去,所以我是參考了@abel533的寫法,實際中使用會碰到什么問題暫時不清楚,如果有園友使用中碰到什么問題,歡迎與我交流.第一次做開源項目,歡迎大家批評指正.
|