使用圖表
本章中將探索在 ExtJS 中使用不一樣類型的圖表並使用一個名爲費用分析的示例項目結束本章所學。如下是將要所學的內容:html
- 圖表類型
- 條形圖 和 柱形圖 圖表
- 區域 和 折線 圖表
- 餅圖 圖表
- 3 D 圖表
- 費用分析 – 示例項目
圖表
在第一章中提過,我說 ExtJS 是一站式的幾乎能知足你對全部的 JavaScript 框架的需求。這固然還包括了圖表功能。git
圖表類型
有三種類型的圖表:笛卡爾圖表,極座標圖表, 和 空間圖表。github
笛卡爾圖表
Ext.chart.CartesianChart (xtype: cartesian or chart)json
一個笛卡爾圖表具備兩個方向:X 和 Y 。默認 X 是水平的,Y 是垂直的。使用笛卡爾座標圖表有柱形圖,條形圖,區域,折線和散射。數組
極座標圖表
Ext.chart.PolarChart (xtype: polar)app
這個圖表有兩個軸:角向和徑向。圖表的標繪值用極座標來表達,有餅圖和雷達圖。框架
空間圖表
Ext.chart.SpaceFillingChart (xtype: spacefilling)工具
這個圖表填充圖表的面積。學習
條形圖和柱狀圖
使用條形圖和柱狀圖,你至少須要提供 store ,axes ,series。字體
基本的柱狀圖
首先,咱們建立一個 store 使用硬編碼的內置數據,如如下代碼所示:
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
|
Ext.define('MyApp.model.Population', {
extend : 'Ext.data.Model',
fields : [ 'year', 'population' ]
});
Ext.define('MyApp.store.Population', {
extend : 'Ext.data.Store',
storeId : 'population',
model : 'MyApp.model.Population',
data : [{
"year" : "1610",
"population" : 350
},{
"year" : "1650",
"population" : 50368
},{
"year" : "1700",
"population" : 250888
},{
"year" : "1750",
"population" : 1170760
},{
"year" : "1800",
"population" : 5308483
},{
"year" : "1900",
"population" : 76212168
},{
"year" : "1950",
"population" : 151325798
},{
"year" : "2000",
"population" : 281421906
},{
"year" : "2010",
"population" : 308745538
}]
});
var store = Ext.create("MyApp.store.Population");
|
使用 Ext.chart.CartesianChart (xtype: cartesian 或 chart ) 建立圖表並應用上面所建立的 store 。
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
|
Ext.create('Ext.Container', {
renderTo : Ext.getBody(),
width : 500,
height : 500,
layout : 'fit',
items : [ {
xtype : 'chart',
insetPadding : {
top : 60,
bottom : 20,
left : 20,
right : 40
},
store : store,
axes : [ {
type : 'numeric',
position : 'left',
grid : true,
title : {
text : 'Population in Millions',
fontSize : 16
}
}, {
type : 'category',
title : {
text : 'Year',
fontSize : 16
},
position : 'bottom'
}],
series : [ {
type : 'bar',
xField : 'year',
yField : [ 'population' ]
} ],
sprites : {
type : 'text',
text : 'United States Population',
font : '25px Helvetica',
width : 120,
height : 35,
x : 100,
y : 40
}
}]
});
|
前面代碼中比較重要的是 axes ,series ,和 sprite 。axes 有三種類型:numeric ,time ,和 category 。
而在 series 中,你能夠看到設置類型爲 bar 。在 ExtJS 中,將會呈現爲柱狀圖或條形圖, 雖然你指定了類型爲 bar ,可是默認是做爲柱狀圖展現的,若是你想要條形圖,須要在圖表配置中設置 flipXY 爲 true 。
這裏 sprites 的配置至關簡單。sprites 是一個可選項,不是必須的。sprites 這裏使用的 text 的類型,就是畫出來一個圖形,設置字體 25 號,寬度 120,高度 35,而且 x 的位置爲 100 ,y 的位置是 40 ,sprites 是ExtJS 中畫圖的一個對象,這裏咱們只是用來寫了一行字。sprites 也能夠接受一個數組,可是這裏咱們只用一個設置。
這個 insetPadding 屬性是用於指定圖表的 padding 。
如下截圖爲輸出結果:
條形圖
如以前所說,爲了獲得條形圖,你可使用一樣的代碼,但要指定 flipXY 爲 true 並改變相應座標的位置,下面把原來 year 換到了左邊。如如下代碼所示:
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
|
Ext.create('Ext.Container', {
renderTo : Ext.getBody(),
width : 500,
height : 500,
layout : 'fit',
items : [ {
xtype : 'chart',
flipXY : true,
insetPadding : {
top : 60,
bottom : 20,
left : 20,
right : 40
},
store : store,
axes : [ {
type : 'numeric',
position : 'bottom',
grid : true,
title : {
text : 'Population in Millions',
fontSize : 16
}
}, {
type : 'category',
title : {
text : 'Year',
fontSize : 16
},
position : 'left'
}],
series : [ {
type : 'bar',
xField : 'year',
yField : [ 'population' ]
}],
sprites : {
type : 'text',
text : 'United States Population',
font : '25px Helvetica',
width : 120,
height : 35,
x : 100,
y : 40
}
}]
});
|
下列截圖爲以上的代碼的輸出結果:
堆疊條形圖
如今假設你想在柱狀圖的每個分類上標繪兩個值。 你能夠將他們堆疊起來或者在每一個分類上使用兩條圖形。
咱們更新柱狀圖例子來展現一個堆疊圖表。爲此咱們須要在 store 中額外添加一個數值字段,同時在 series 中咱們須要爲 yField 指定兩個字段。你也能夠堆疊超過兩個字段,可是本例中咱們只用兩個字段,看看下面的代碼:
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
|
Ext.define('MyApp.model.Population', {
extend : 'Ext.data.Model',
fields : [ 'year', 'total', 'slaves' ]
});
Ext.define('MyApp.store.Population', {
extend : 'Ext.data.Store',
storeId : 'population',
model : 'MyApp.model.Population',
data : [{
"year" : "1790",
"total" : 3.9,
"slaves" : 0.7
},{
"year" : "1800",
"total" : 5.3,
"slaves" : 0.9
},{
"year" : "1810",
"total" : 7.2,
"slaves" : 1.2
},{
"year" : "1820",
"total" : 9.6,
"slaves" : 1.5
},{
"year" : "1830",
"total" : 12.9,
"slaves" : 2
},{
"year" : "1840",
"total" : 17,
"slaves" : 2.5
},{
"year" : "1850",
"total" : 23.2,
"slaves" : 3.2
},{
"year" : "1860",
"total" : 31.4,
"slaves" : 4
}]
});
var store = Ext.create("MyApp.store.Population");
Ext.create('Ext.Container', {
renderTo : Ext.getBody(),
width : 500,
height : 500,
layout : 'fit',
items : [ {
xtype : 'cartesian',
store : store,
insetPadding : {
top : 60,
bottom : 20,
left : 20,
right : 40
},
axes : [ {
type : 'numeric',
position : 'left',
grid : true,
title : {
text : 'Population in Millions',
fontSize : 16
}
}, {
type : 'category',
title : {
text : 'Year',
fontSize : 16
},
position : 'bottom'
}],
series : [ {
type : 'bar',
xField : 'year',
yField : [ 'total', 'slaves' ]
}],
sprites : {
type : 'text',
text : 'United States Slaves Distribution 1790 to 1860',
font : '20px Helvetica',
width : 120,
height : 35,
x : 60,
y : 40
}
}]
});
|
堆疊柱狀圖的輸出以下列截圖:
若是你想呈現多個字段,而且讓它們未疊加,那麼只須要簡單的設置 series 的 stacked 屬性爲 false 便可,請看如下輸出:
在圖表中還有不少可用的選項。讓咱們瞧一瞧一些經常使用的選項:
- tooltip: 這個屬性能夠在 series 裏添加一個提示信息,鼠標放在每一個柱狀圖上是會提示相應的信息。
- legend: 這能夠呈現圖表的說明到任意的四個邊上
- sprites: 這個能夠接收一個數組對象,上面介紹過啦,它是能夠在你圖標上添加一些圖形,文本等等。
下面這是使用的相同的 store ,只是用了一些上面提的其餘的選項:
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
|
Ext.create('Ext.Container', {
renderTo: Ext.getBody(),
width: 500,
height: 500,
layout: 'fit',
items: [{
xtype: 'chart',
legend: { docked: 'bottom' },
insetPadding: {
top: 60,
bottom: 20,
left: 20,
right: 40
},
store: store,
axes: [{
type: 'numeric',
position: 'left',
grid: true,
title: {
text: 'Population in Millions',
fontSize: 16
},
minimum: 0,
}, {
type: 'category',
title: {
text: 'Year',
fontSize: 16
},
position: 'bottom',
}],
series: [{
type: 'bar',
xField: 'year',
stacked: false,
title: ['Total', 'Slaves'],
yField: ['total', 'slaves'],
tooltip: {
trackMouse: true,
style: 'background: #fff',
renderer: function (storeItem, item) {
this.setHtml('In ' + storeItem.get('year') + ' ' + item. field + ' population was ' + storeItem.get(item.field) + ' m');
}
}
}],
sprites: [{
type: 'text',
text: 'United States Slaves Distribution 1790 to 1860',
font: '20px Helvetica',
width: 120,
height: 35,
x: 60,
y: 40
},{
type: 'text',
text: 'Source: http://www.wikipedia.org',
fontSize: 10,
x: 12,
y: 440
}]
}]
});
|
輸出你看到頁腳,提示信息和說明信息都在下圖:
3D 柱狀圖
若是你改變 series 的類型爲 bar3d ,就能得到 3D 的柱狀圖,以下列截圖所示:
區域和折線圖
區域和折線圖也屬因而笛卡爾圖表。
區域圖表
呈現一個區域圖,使用下列代碼簡單的替換前面的例子裏的 series :
1
2
3
4
5
6
7
8
9
10
11
|
series: [ {
type : 'area',
xField : 'year',
stacked : false,
title : [ 'Total', 'slaves' ],
yField : [ 'total', 'slaves' ],
style : {
stroke : "#94ae0a",
fillOpacity : 0.6,
}
} ]
|
以上代碼所示的輸出:
相似於堆疊柱狀圖,你也能夠在 series 中設置 stacked 爲true 來實現堆疊。若是你在以前例子上將 stacked 改成 true ,那麼將得到下列結果輸出:
折線圖
使用下列的配置在上面的例子中的 series ,折線圖顯示圖下圖:
1
2
3
4
5
6
7
8
9
10
11
|
series: [ {
type : 'line',
xField : 'year',
title : [ 'Total' ],
yField : [ 'total' ]
},{
type : 'line',
xField : 'year',
title : [ 'Slaves' ],
yField : [ 'slaves' ]
}]
|
餅圖
這是一個在不少應用中都很經常使用的圖表和報表工具。呈現一個餅圖使用 Ext.chart.PolarChart (xtype: polar) 。
基本的餅圖
指定類型爲 pie ,還要指定 angleField 和 label 來呈現餅圖。angleField 這是角度字段,如如下代碼所示:
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
|
Ext.define('MyApp.store.Expense', {
extend : 'Ext.data.Store',
alias : 'store.expense',
fields : [ 'cat', 'spent' ],
data : [ {
"cat" : "Restaurant",
"spent" : 100
}, {
"cat" : "Travel",
"spent" : 150
}, {
"cat" : "Insurance",
"spent" : 500
}, {
"cat" : "Rent",
"spent" : 1000
}, {
"cat" : "Groceries",
"spent" : 400
}, {
"cat" : "Utilities",
"spent" : 300
} ]
});
var store = Ext.create("MyApp.store.Expense");
Ext.create('Ext.Container',{
renderTo : Ext.getBody(),
width : 600,
height : 500,
layout : 'fit',
items : [ {
xtype : 'polar',
legend : {
docked : 'bottom'
},
insetPadding : {
top : 100,
bottom : 20,
left : 20,
right : 40
},
store : store,
series : [ {
type : 'pie',
angleField : 'spent',
label : {
field : 'cat',
},
tooltip : {
trackMouse : true,
renderer : function(storeItem, item) {
var value = ((parseFloat(storeItem.get('spent')/ storeItem.store.sum('spent')) * 100.0).toFixed(2));
this.setHtml(storeItem.get('cat') + ': ' + value + '%');
}
}
} ]
} ]
});
|
圓環餅圖
這僅須要在以前的例子中設置 donut 屬性的值爲 40 ,你將獲取下列圖表。donut 這個值是半徑的百分比:
3D餅圖
在 ExtJS 6 中,對 3D 餅圖作出了一些改進。如今 3D 餅圖支持 label 和可配置的 3D 切面,例如厚度,變形等等。
咱們使用一樣的 model 和 store 使用前面餅圖的例子建立一個 3D 餅圖,以下:
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
|
Ext.create('Ext.Container',{
renderTo : Ext.getBody(),
width : 600,
height : 500,
layout : 'fit',
items : [ {
xtype : 'polar',
legend : {
docked : 'bottom'
},
insetPadding : {
top : 100,
bottom : 20,
left : 80,
right : 80
},
store : store,
series : [ {
type : 'pie3d',
donut : 50,
thickness : 70,
distortion : 0.5,
angleField : 'spent',
label : {
field : 'cat'
},
tooltip : {
trackMouse : true,
renderer : function(storeItem, item) {
var value = ((parseFloat(storeItem.get('spent')/ storeItem.store.sum('spent')) * 100.0).toFixed(2));
this.setHtml(storeItem.get('cat') + ': ' + value+ '%');
}
}
} ]
} ]
});
|
下面的圖片顯示了上面代碼的輸出:
費用分析器 – 示例項目
又是項目時間,如今你已經瞭解了 ExtJS 中不一樣的圖表類型,咱們來建立一個示例項目名爲 費用分析器。下面是最終設計效果:
咱們使用 Sencha Cmd 來構建應用。運行下列命令:
1
|
sencha -sdk <path to SDK>/ext-6.0.0.415/ generate app EA ./expenseanalyzer
|
以後咱們移除全部沒必要要的文件和代碼,添加一些額外的文件。目錄結構以下:
- 這裏只有一些重要文件的代碼,完整的代碼在這裏 https://github. com/ananddayalan/extjs-by-example-expense-analyzer
下列代碼是建立 grid 。這個 List 視圖繼承自 Ext.grid.Panel ,數據使用 expense store ,它有三列:
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
|
Ext.define('EA.view.main.List', {
extend : 'Ext.grid.Panel',
xtype : 'mainlist',
maxHeight : 400,
requires : [ 'EA.store.Expense' ],
title : 'Year to date expense by category',
store : {
type : 'expense'
},
columns : {
defaults : {
flex : 1
},
items : [ {
text : 'Category',
dataIndex : 'cat'
}, {
formatter : "date('F')",
text : 'Month',
dataIndex : 'date'
}, {
text : 'Spent',
dataIndex : 'spent'
} ]
}
});
|
我並無在這裏使用分頁。maxHeight 是用於限制 grid 的高度,同時開啓滾動條,由於有更多的數據。
如下代碼建立了 expense store 。這個 store 使用了內嵌數據。這裏咱們並無單獨爲 store 建立 model :
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
|
Ext.define('EA.store.Expense', {
extend : 'Ext.data.Store',
alias : 'store.expense',
storeId : 'expense',
fields : [ {
name : 'date',
type : 'date'
},
'cat',
'spent'
],
data : {
items : [{
"date" : "1/1/2015",
"cat" : "Restaurant",
"spent" : 100
},{
"date" : "1/1/2015",
"cat" : "Travel",
"spent" : 22
},{
"date" : "1/1/2015",
"cat" : "Insurance",
"spent" : 343
}]
},
proxy : {
type : 'memory',
reader : {
type : 'json',
rootProperty : 'items'
}
}
});
|
繼續建立柱狀圖。在柱狀圖中咱們將使用另一個 store 叫作 expensebyMonth store ,咱們將從 expense 的數據填充進來。
下列 3D 柱狀圖有兩個 axis 類型: numeric 和 category 。咱們使用日期字段的月部分做爲 category 。renderer 屬性用於呈現日期字段的月份部分:
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
|
Ext.define('EA.view.main.Bar', {
extend : 'Ext.chart.CartesianChart',
requires : [ 'Ext.chart.axis.Category',
'Ext.chart.series.Bar3D',
'Ext.chart.axis.Numeric',
'Ext.chart.interactions.ItemHighlight' ],
xtype : 'mainbar',
height : 500,
padding : {
top : 50,
bottom : 20,
left : 100,
right : 100
},
legend : {
docked : 'bottom'
},
insetPadding : {
top : 100,
bottom : 20,
left : 20,
right : 40
},
store : {
type : 'expensebyMonthStore'
},
axes : [ {
type : 'numeric',
position : 'left',
grid : true,
minimum : 0,
title : {
text : 'Spendings in $',
fontSize : 16
}
}, {
type : 'category',
position : 'bottom',
title : {
text : 'Month',
fontSize : 16
},
label : {
font : 'bold Arial',
rotate : {
degrees : 300
}
},
renderer : function(date) {
return [ "Jan", "Feb", "Mar", "Apr", "May" ][date.getMonth()];
}
} ],
series : [ {
type : 'bar3d',
xField : 'date',
stacked : false,
title : [ 'Total' ],
yField : [ 'total' ]
} ],
sprites : [ {
type : 'text',
text : 'Expense by Month',
font : '20px Helvetica',
width : 120,
height : 35,
x : 60,
y : 40
} ]
});
|
如今爲上面的柱狀圖建立 store 。model 爲 MyApp.model.ExpensebyMonth 。這個 store 將用來顯示每月的花費總數。數據是經過對 expense store 的日期字段進行分組後填充的,如今咱們瞧一瞧 data 屬性是如何配置填充數據的:
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
|
Ext.define('MyApp.model.ExpensebyMonth', {
extend : 'Ext.data.Model',
fields : [ {
name : 'date',
type : 'date'
}, 'total' ]
});
Ext.define('MyApp.store.ExpensebyMonth', {
extend : 'Ext.data.Store',
alias : 'store.expensebyMonthStore',
model : 'MyApp.model.ExpensebyMonth',
data : (function() {
var data = [];
var expense = Ext.createByAlias('store.expense');
expense.group('date');
var groups = expense.getGroups();
groups.each(function(group) {
data.push({
date : group.config.groupKey,
total :group.sum('spent')
});
});
return data;
})()
});
|
如下代碼用於生成餅圖。這個圖表使用的的 store 是 expense ,但只顯示了一次選擇一個月的數據。在主視圖上添加了一個下拉框用於選擇月份。
這個 beforerender 事件是用於過濾 expense store 裏用於顯示的數據,只加載一月份的數據:
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
|
Ext.define('EA.view.main.Pie', {
extend : 'Ext.chart.PolarChart',
requires : [ 'Ext.chart.series.Pie3D' ],
xtype : 'mainpie',
height : 800,
legend : {
docked : 'bottom'
},
insetPadding : {
top : 100,
bottom : 20,
left : 80,
right : 80
},
listeners : {
beforerender : function() {
var dateFiter = new Ext.util.Filter({
filterFn : function(item) {
return item.data.date.getMonth() == 0;
}
});
Ext.getStore('expense').addFilter(dateFiter);
}
},
store : {
type : 'expense'
},
series : [ {
type : 'pie3d',
donut : 50,
thickness : 70,
distortion : 0.5,
angleField : 'spent',
label : {
field : 'cat',
}
} ]
});
|
截止目前,咱們建立好了 grid ,柱狀圖,餅圖,和這個應用所須要的 store 。如今須要在主視圖上把他們聯繫起來。如下代碼展現了 main 視圖的經典工具包裏的片斷。main 視圖是一個選項卡控件,爲每一個選項卡指定視圖:
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
|
Ext.define('EA.view.main.Main', {
extend : 'Ext.tab.Panel',
xtype : 'app-main',
requires : [
'Ext.plugin.Viewport',
'Ext.window.MessageBox',
'EA.view.main.MainController',
'EA.view.main.List',
'EA.view.main.Bar',
'EA.view.main.Pie'
],
controller : 'main',
autoScroll : true,
ui : 'navigation',
// Truncated code
items : [ {
title : 'Year to Date',
iconCls : 'fa-bar-chart',
items : [ {
html : '<h3>Your average expense per month is: ' +Ext.createByAlias('store.expensebyMonthStore').average('total') +'</h3>',
height : 70,
},{
xtype : 'mainlist'
},{
xtype : 'mainbar'
}]
},{
title : 'By Month',
iconCls : 'fa-pie-chart',
items : [ {
xtype : 'combo',
value : 'Jan',
fieldLabel : 'Select Month',
store : [ 'Jan', 'Feb', 'Mar', 'Apr', 'May' ],
listeners : {
select : 'onMonthSelect'
}
}, {
xtype : 'mainpie'
} ]
} ]
});
|
總結
在本章中,咱們在 ExtJS 中學習到不一樣的圖表。而且建立了一個示例項目來演示他們的應用。