标签:des style class blog code java
在Extjs 中, 单一的 Column Chart 的展示效果如上。
定义的步骤如下:
1. 创建一个 Ext.chart.Chart
2. 创建两个坐标轴, axes
一个 Category 类型的横坐标用来显示日期
一个Numeric 类型的纵坐标用来显示数据
3. 配置显示的图 series
配置 column 类型的柱状图。
具体代码如下:
<!--
Author : oscar999
Date :
ALL RIGHTS RESERVED
-->
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="../lib/extjs/ext-all.js"></script>
<link rel="stylesheet" type="text/css" href="../lib/extjs/resources/ext-theme-neptune/ext-theme-neptune-all.css" />
<script>
Ext.onReady(function(){
window.generateData = function(n, floor){
var data = [],
p = (Math.random() * 11) + 1,
i;
floor = (!floor && floor !== 0)? 20 : floor;
for (i = 0; i < (n || 12); i++) {
data.push({
name: Ext.Date.monthNames[i % 12],
data1: Math.floor(Math.max((Math.random() * 100), floor)),
data2: Math.floor(Math.max((Math.random() * 100), floor)),
data3: Math.floor(Math.max((Math.random() * 100), floor)),
data4: Math.floor(Math.max((Math.random() * 100), floor)),
data5: Math.floor(Math.max((Math.random() * 100), floor)),
data6: Math.floor(Math.max((Math.random() * 100), floor)),
data7: Math.floor(Math.max((Math.random() * 100), floor)),
data8: Math.floor(Math.max((Math.random() * 100), floor)),
data9: Math.floor(Math.max((Math.random() * 100), floor))
});
}
return data;
};
var store1 = Ext.create(‘Ext.data.JsonStore‘, {
fields: [‘name‘, ‘data1‘, ‘data2‘, ‘data3‘, ‘data4‘, ‘data5‘, ‘data6‘, ‘data7‘, ‘data9‘, ‘data9‘],
data: generateData()
});
var chart = Ext.create(‘Ext.chart.Chart‘, {
style: ‘background:#fff‘,
animate: true,
shadow: true,
store: store1,
//maxWidth: 500,
//columnWidth : 0.1,
axes: [{
type: ‘Numeric‘,
position: ‘left‘,
fields: [‘data1‘],
label: {
renderer: Ext.util.Format.numberRenderer(‘0,0‘)
},
title: ‘Number of Hits‘,
grid: true,
minimum: 0
}, {
type: ‘Category‘,
position: ‘bottom‘,
fields: [‘name‘],
//categoryNames:new String("111"),
title: ‘Month of the Year‘
}],
series: [{
type: ‘column‘,
axis: ‘left‘,
highlight: true,
tips: {
trackMouse: true,
width: 140,
height: 28,
renderer: function(storeItem, item) {
this.setTitle(storeItem.get(‘name‘) + ‘: ‘ + storeItem.get(‘data1‘) + ‘ $‘);
}
},
label: {
display: ‘insideEnd‘,
‘text-anchor‘: ‘middle‘,
field: ‘data1‘,
//renderer: Ext.util.Format.numberRenderer(‘0‘),
orientation: ‘vertical‘,
color: ‘#FFF‘
},
style:{
opacity: 0.95
//,width:100
},
//xPadding:{left:100,right:100},
xField: ‘name‘,
yField: ‘data1‘
}]
});
var win = Ext.create(‘Ext.window.Window‘, {
width: 800,
height: 600,
minHeight: 400,
minWidth: 550,
hidden: false,
maximizable: true,
title: ‘Column Chart‘,
autoShow: true,
layout: ‘fit‘,
tbar: [{
text: ‘Save Chart‘,
handler: function() {
Ext.MessageBox.confirm(‘Confirm Download‘, ‘Would you like to download the chart as an image?‘, function(choice){
if(choice == ‘yes‘){
chart.save({
type: ‘image/png‘
});
}
});
}
}, {
text: ‘Reload Data‘,
handler: function() {
// Add a short delay to prevent fast sequential clicks
window.loadTask.delay(100, function() {
store1.loadData(generateData());
});
}
}],
items: chart
});
});
</script>
</head>
<body>
</body>
</html>针对上面的例子, 坐标轴的长度是Extjs根据数据大小自动运算并设置的。
如果需要手动定义这个长度的话,改如何设置呢?
对于Numeric这样的坐标轴来说, 有maximum 和 minimun 这样的参数可以配置。
而且配置也很简单了, 就不多介绍了。
这里只是对红色的部分做一个伏笔(这种设置对于配置 堆叠的图形不使用)
有的状况下, 可能会使用多个图形,
因为图形的范围不同,可能需要使用两个纵坐标轴。
类似的情景可以是这样:
有三个图, 两个柱状图, 一个折线图
折线图和柱状图的数据范围或是单位可能不同。
这里看上去好像是一个折线图和一个柱状图。
其实是有两个柱状图, 只不过一个被另一个盖住了。
出现这种状况的原因是在定义的时候, 往series 中添加了两个column 的chart.
这种状况的源码是:
<!--
Author : oscar999
Date :
ALL RIGHTS RESERVED
-->
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="../lib/extjs/ext-all.js"></script>
<link rel="stylesheet" type="text/css" href="../lib/extjs/resources/ext-theme-neptune/ext-theme-neptune-all.css" />
<script>
Ext.onReady(function(){
window.generateData = function(n, floor){
var data = [],
p = (Math.random() * 11) + 1,
i;
floor = (!floor && floor !== 0)? 20 : floor;
for (i = 0; i < (n || 12); i++) {
data.push({
name: Ext.Date.monthNames[i % 12],
data1: (i+1)*8,
data2: (i+1)*10,
data3: (i+1)*8
});
}
return data;
};
var store1 = Ext.create(‘Ext.data.JsonStore‘, {
fields: [‘name‘, ‘data1‘, ‘data2‘, ‘data3‘, ‘data4‘, ‘data5‘, ‘data6‘, ‘data7‘, ‘data9‘, ‘data9‘],
data: generateData()
});
var chart = Ext.create(‘Ext.chart.Chart‘, {
style: ‘background:#fff‘,
animate: true,
shadow: true,
store: store1,
legend:‘right‘,
axes: [{
type: ‘Numeric‘,
position: ‘left‘,
fields: [‘data1‘,‘data2‘],
label: {
renderer: Ext.util.Format.numberRenderer(‘0,0‘)
},
title: ‘Number of Hits‘,
grid: true
},{
type: ‘Numeric‘,
position: ‘right‘,
fields: [‘data3‘],
label: {
renderer: Ext.util.Format.numberRenderer(‘0,0‘)
},
//title: ‘Number of Hits‘,
grid: true
}, {
type: ‘Category‘,
position: ‘bottom‘,
fields: [‘name‘],
title: ‘Month of the Year‘
}],
series: [{
type: ‘column‘,
axis: ‘left‘,
highlight: true,
tips: {
trackMouse: true,
width: 140,
height: 28,
renderer: function(storeItem, item) {
this.setTitle(storeItem.get(‘name‘) + ‘: ‘ + storeItem.get(‘data1‘) + ‘ $‘);
}
},
label: {
display: ‘insideEnd‘,
‘text-anchor‘: ‘middle‘,
field: ‘data1‘,
//renderer: Ext.util.Format.numberRenderer(‘0‘),
orientation: ‘vertical‘,
color: ‘#FFF‘
},
style:{
opacity: 0.95
//,width:100
},
//xPadding:{left:100,right:100},
xField: ‘name‘,
yField: [‘data1‘]
}
,{
type: ‘column‘,
axis: ‘left‘,
highlight: true,
tips: {
trackMouse: true,
width: 140,
height: 28,
renderer: function(storeItem, item) {
this.setTitle(storeItem.get(‘name‘) + ‘: ‘ + storeItem.get(‘data2‘) + ‘ $‘);
}
},
label: {
display: ‘insideEnd‘,
‘text-anchor‘: ‘middle‘,
field: [‘data1‘,‘data2‘],
//renderer: Ext.util.Format.numberRenderer(‘0‘),
orientation: ‘vertical‘,
color: ‘#FFF‘
},
style:{
opacity: 0.95
//,width:100
},
//xPadding:{left:100,right:100},
xField: ‘name‘,
yField: [‘data2‘]
}
,
{
type: ‘line‘,
axis: ‘right‘,
highlight: true,
tips: {
trackMouse: true,
width: 140,
height: 28,
renderer: function(storeItem, item) {
this.setTitle(storeItem.get(‘name‘) + ‘: ‘ + storeItem.get(‘data3‘) + ‘ $‘);
}
},
label: {
display: ‘insideEnd‘,
‘text-anchor‘: ‘middle‘,
field: ‘data3‘,
//renderer: Ext.util.Format.numberRenderer(‘0‘),
orientation: ‘vertical‘,
color: ‘#FFF‘
},
style:{
opacity: 0.95
//,width:100
},
//xPadding:{left:100,right:100},
xField: ‘name‘,
yField: ‘data3‘
}]
});
var win = Ext.create(‘Ext.window.Window‘, {
width: 800,
height: 600,
minHeight: 400,
minWidth: 550,
hidden: false,
maximizable: true,
title: ‘Column Chart‘,
autoShow: true,
layout: ‘fit‘,
tbar: [{
text: ‘Save Chart‘,
handler: function() {
Ext.MessageBox.confirm(‘Confirm Download‘, ‘Would you like to download the chart as an image?‘, function(choice){
if(choice == ‘yes‘){
chart.save({
type: ‘image/png‘
});
}
});
}
}, {
text: ‘Reload Data‘,
handler: function() {
// Add a short delay to prevent fast sequential clicks
window.loadTask.delay(100, function() {
store1.loadData(generateData());
});
}
}],
items: chart
});
});
</script>
</head>
<body>
</body>
</html>我们要的效果应该是这样:
这是完美的呈现方式。
完美方式实现的思想是:
1 创建两个坐标轴, axes
一个 Category 类型的横坐标用来显示日期
一个Numeric 类型的纵坐标用来显示柱状图数据一个Numeric 类型的纵坐标用来显示折线图数据
2. series 添加一个 column Chart. stacked.
以上定义完成之后, 会发生基本上都正常, 但是有一点就是, 左右的两个纵坐标的尺度可能不同。
通过配置maximum 和maximum 来设置坐标并不会生效。
这里就要提到上面框出的maximum配置的红色部分了, 因为这个配置对于堆叠的图已经不适用了。
为什么会出现左右坐标不一致的状况, 看一看Extjs 的 Ext.chart.axis.Numeric 的定义
原来是这个地方有限制。这应该是Extjs 有意为之了, 至于原因是什么,尚不可知。
不管这样,先去除这个限制得到想要的效果。
解决方案就是定义一个和 Ext.chart.axis.Numeric 类似的坐标定义
/**
* Add by Oscar999
*/
Ext.define(‘Ext.chart.axis.StackedNumeric‘, {
/* Begin Definitions */
extend: ‘Ext.chart.axis.Axis‘,
alternateClassName: ‘Ext.chart.StackedNumericAxis‘,
/* End Definitions */
type: ‘StackedNumeric‘,
// @private
isNumericAxis: true,
alias: ‘axis.stackednumeric‘,
uses: [‘Ext.data.Store‘],
constructor: function(config) {
var me = this,
hasLabel = !!(config.label && config.label.renderer),
label;
me.callParent([config]);
label = me.label;
if (config.constrain == null) {
me.constrain = (config.minimum != null && config.maximum != null);
}
if (!hasLabel) {
label.renderer = function(v) {
return me.roundToDecimal(v, me.decimals);
};
}
},
roundToDecimal: function(v, dec) {
var val = Math.pow(10, dec || 0);
return Math.round(v * val) / val;
},
/**
* @cfg {Number} minimum
* The minimum value drawn by the axis. If not set explicitly, the axis
* minimum will be calculated automatically. It is ignored for stacked charts.
*/
minimum: NaN,
/**
* @cfg {Number} maximum
* The maximum value drawn by the axis. If not set explicitly, the axis
* maximum will be calculated automatically. It is ignored for stacked charts.
*/
maximum: NaN,
/**
* @cfg {Boolean} constrain
* If true, the values of the chart will be rendered only if they belong between minimum and maximum.
* If false, all values of the chart will be rendered, regardless of whether they belong between minimum and maximum or not.
* Default‘s true if maximum and minimum is specified. It is ignored for stacked charts.
*/
constrain: true,
/**
* @cfg {Number} decimals
* The number of decimals to round the value to.
*/
decimals: 2,
/**
* @cfg {String} scale
* The scaling algorithm to use on this axis. May be "linear" or
* "logarithmic". Currently only linear scale is implemented.
* @private
*/
scale: "linear",
// @private constrains to datapoints between minimum and maximum only
doConstrain: function() {
var me = this,
chart = me.chart,
store = chart.getChartStore(),
items = store.data.items,
d, dLen, record,
series = chart.series.items,
fields = me.fields,
ln = fields.length,
range = me.calcEnds(),
min = range.from, max = range.to, i, l,
useAcum = false,
value, data = [],
addRecord;
for (d = 0, dLen = items.length; d < dLen; d++) {
addRecord = true;
record = items[d];
for (i = 0; i < ln; i++) {
value = record.get(fields[i]);
if (me.type == ‘Time‘ && typeof value == "string") {
value = Date.parse(value);
}
if (+value < +min) {
addRecord = false;
break;
}
if (+value > +max) {
addRecord = false;
break;
}
}
if (addRecord) {
data.push(record);
}
}
chart.setSubStore(new Ext.data.Store({
model: store.model,
data: data
}));
},
/**
* @cfg {String} position
* Indicates the position of the axis relative to the chart
*/
position: ‘left‘,
/**
* @cfg {Boolean} adjustMaximumByMajorUnit
* Indicates whether to extend maximum beyond data‘s maximum to the nearest
* majorUnit.
*/
adjustMaximumByMajorUnit: false,
/**
* @cfg {Boolean} adjustMinimumByMajorUnit
* Indicates whether to extend the minimum beyond data‘s minimum to the
* nearest majorUnit.
*/
adjustMinimumByMajorUnit: false,
// applying constraint
processView: function() {
var me = this;
if (me.constrain) {
me.doConstrain();
}
},
// @private apply data.
applyData: function() {
this.callParent();
return this.calcEnds();
}
});下面给出一个放在同一份文件中完整的源码:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="../lib/extjs/ext-all.js"></script>
<script>
/*Ext.define(‘mtk.chart.axis.Numeric‘,
{
extend : ‘Ext.chart.axis.Numeric‘,
type: ‘stackedNumeric‘,
initComponent: function(config) {
this.processView = function() {
var me = this,
chart = me.chart,
series = chart.series.items,
i, l;
for (i = 0, l = series.length; i < l; i++) {
if (series[i].stacked) {
// Do not constrain stacked charts (bar, column, or area).
delete me.minimum;
delete me.maximum;
me.constrain = false;
break;
}
}
if (me.constrain) {
me.doConstrain();
}
};
this.callParent([config]);
}
});*/
Ext.define(‘Ext.chart.axis.StackedNumeric‘, {
/* Begin Definitions */
extend: ‘Ext.chart.axis.Axis‘,
alternateClassName: ‘Ext.chart.StackedNumericAxis‘,
/* End Definitions */
type: ‘StackedNumeric‘,
// @private
isNumericAxis: true,
alias: ‘axis.stackednumeric‘,
uses: [‘Ext.data.Store‘],
constructor: function(config) {
var me = this,
hasLabel = !!(config.label && config.label.renderer),
label;
me.callParent([config]);
label = me.label;
if (config.constrain == null) {
me.constrain = (config.minimum != null && config.maximum != null);
}
if (!hasLabel) {
label.renderer = function(v) {
return me.roundToDecimal(v, me.decimals);
};
}
},
roundToDecimal: function(v, dec) {
var val = Math.pow(10, dec || 0);
return Math.round(v * val) / val;
},
/**
* @cfg {Number} minimum
* The minimum value drawn by the axis. If not set explicitly, the axis
* minimum will be calculated automatically. It is ignored for stacked charts.
*/
minimum: NaN,
/**
* @cfg {Number} maximum
* The maximum value drawn by the axis. If not set explicitly, the axis
* maximum will be calculated automatically. It is ignored for stacked charts.
*/
maximum: NaN,
/**
* @cfg {Boolean} constrain
* If true, the values of the chart will be rendered only if they belong between minimum and maximum.
* If false, all values of the chart will be rendered, regardless of whether they belong between minimum and maximum or not.
* Default‘s true if maximum and minimum is specified. It is ignored for stacked charts.
*/
constrain: true,
/**
* @cfg {Number} decimals
* The number of decimals to round the value to.
*/
decimals: 2,
/**
* @cfg {String} scale
* The scaling algorithm to use on this axis. May be "linear" or
* "logarithmic". Currently only linear scale is implemented.
* @private
*/
scale: "linear",
// @private constrains to datapoints between minimum and maximum only
doConstrain: function() {
var me = this,
chart = me.chart,
store = chart.getChartStore(),
items = store.data.items,
d, dLen, record,
series = chart.series.items,
fields = me.fields,
ln = fields.length,
range = me.calcEnds(),
min = range.from, max = range.to, i, l,
useAcum = false,
value, data = [],
addRecord;
for (d = 0, dLen = items.length; d < dLen; d++) {
addRecord = true;
record = items[d];
for (i = 0; i < ln; i++) {
value = record.get(fields[i]);
if (me.type == ‘Time‘ && typeof value == "string") {
value = Date.parse(value);
}
if (+value < +min) {
addRecord = false;
break;
}
if (+value > +max) {
addRecord = false;
break;
}
}
if (addRecord) {
data.push(record);
}
}
chart.setSubStore(new Ext.data.Store({
model: store.model,
data: data
}));
},
/**
* @cfg {String} position
* Indicates the position of the axis relative to the chart
*/
position: ‘left‘,
/**
* @cfg {Boolean} adjustMaximumByMajorUnit
* Indicates whether to extend maximum beyond data‘s maximum to the nearest
* majorUnit.
*/
adjustMaximumByMajorUnit: false,
/**
* @cfg {Boolean} adjustMinimumByMajorUnit
* Indicates whether to extend the minimum beyond data‘s minimum to the
* nearest majorUnit.
*/
adjustMinimumByMajorUnit: false,
// applying constraint
processView: function() {
/*var me = this,
chart = me.chart,
series = chart.series.items,
i, l;
for (i = 0, l = series.length; i < l; i++) {
if (series[i].stacked) {
// Do not constrain stacked charts (bar, column, or area).
delete me.minimum;
delete me.maximum;
me.constrain = false;
break;
}
}
if (me.constrain) {
me.doConstrain();
}*/
var me = this;
if (me.constrain) {
me.doConstrain();
}
},
// @private apply data.
applyData: function() {
this.callParent();
return this.calcEnds();
}
});
</script>
<link rel="stylesheet" type="text/css" href="../lib/extjs/resources/ext-theme-neptune/ext-theme-neptune-all.css" />
<script>
Ext.onReady(function(){
window.generateData = function(n, floor){
var data = [],
p = (Math.random() * 11) + 1,
i;
floor = (!floor && floor !== 0)? 20 : floor;
for (i = 0; i < (n || 12); i++) {
data.push({
name: Ext.Date.monthNames[i % 12],
/*data1: Math.floor(Math.max((Math.random() * 100), floor)),
data2: Math.floor(Math.max((Math.random() * 100), floor)),
data3: Math.floor(Math.max((Math.random() * 100), floor)),
data4: Math.floor(Math.max((Math.random() * 100), floor)),
data5: Math.floor(Math.max((Math.random() * 100), floor)),
data6: Math.floor(Math.max((Math.random() * 100), floor)),
data7: Math.floor(Math.max((Math.random() * 100), floor)),
data8: Math.floor(Math.max((Math.random() * 100), floor)),
data9: Math.floor(Math.max((Math.random() * 100), floor))*/
data1: (i+1)*8,
data2: (i+1)*8,
data3: (i+1)*8,
data4: (i+1)*8,
data5: (i+1)*8,
data6: (i+1)*8,
data7: (i+1)*8,
data8: (i+1)*8,
data9: (i+1)*8
});
}
return data;
};
var store1 = Ext.create(‘Ext.data.JsonStore‘, {
fields: [‘name‘, ‘data1‘, ‘data2‘, ‘data3‘, ‘data4‘, ‘data5‘, ‘data6‘, ‘data7‘, ‘data9‘, ‘data9‘],
data: generateData()
});
var chart = Ext.create(‘Ext.chart.Chart‘, {
style: ‘background:#fff‘,
animate: true,
shadow: true,
store: store1,
//maxWidth: 500,
//columnWidth : 0.1,
legend:‘right‘,
axes: [{
type: ‘StackedNumeric‘,
position: ‘left‘,
fields: [‘data1‘,‘data2‘],
label: {
renderer: Ext.util.Format.numberRenderer(‘0,0‘)
},
title: ‘Number of Hits‘,
grid: true,
minimum: 0,
maximum:200
},{
type: ‘StackedNumeric‘,
position: ‘right‘,
fields: [‘data3‘],
label: {
renderer: Ext.util.Format.numberRenderer(‘0,0‘)
},
//title: ‘Number of Hits‘,
grid: true,
minimum: 0,
maximum:200
}, {
type: ‘Category‘,
position: ‘bottom‘,
fields: [‘name‘],
//categoryNames:new String("111"),
title: ‘Month of the Year‘
}],
series: [{
type: ‘column‘,
axis: ‘left‘,
//stacked:false,
stacked:true,
highlight: true,
tips: {
trackMouse: true,
width: 140,
height: 28,
renderer: function(storeItem, item) {
this.setTitle(storeItem.get(‘name‘) + ‘: ‘ + storeItem.get(‘data1‘) + ‘ $‘);
}
},
label: {
display: ‘insideEnd‘,
‘text-anchor‘: ‘middle‘,
field: [‘data1‘,‘data2‘],
//renderer: Ext.util.Format.numberRenderer(‘0‘),
orientation: ‘vertical‘,
color: ‘#FFF‘
},
style:{
opacity: 0.95
//,width:100
},
//xPadding:{left:100,right:100},
xField: ‘name‘,
yField: [‘data1‘,‘data2‘]
}
,
{
type: ‘line‘,
axis: ‘right‘,
highlight: true,
tips: {
trackMouse: true,
width: 140,
height: 28,
renderer: function(storeItem, item) {
this.setTitle(storeItem.get(‘name‘) + ‘: ‘ + storeItem.get(‘data3‘) + ‘ $‘);
}
},
label: {
display: ‘insideEnd‘,
‘text-anchor‘: ‘middle‘,
field: ‘data3‘,
//renderer: Ext.util.Format.numberRenderer(‘0‘),
orientation: ‘vertical‘,
color: ‘#FFF‘
},
style:{
opacity: 0.95
//,width:100
},
//xPadding:{left:100,right:100},
xField: ‘name‘,
yField: ‘data3‘
}]
});
var win = Ext.create(‘Ext.window.Window‘, {
width: 800,
height: 600,
minHeight: 400,
minWidth: 550,
hidden: false,
maximizable: true,
title: ‘Column Chart‘,
autoShow: true,
layout: ‘fit‘,
tbar: [{
text: ‘Save Chart‘,
handler: function() {
Ext.MessageBox.confirm(‘Confirm Download‘, ‘Would you like to download the chart as an image?‘, function(choice){
if(choice == ‘yes‘){
chart.save({
type: ‘image/png‘
});
}
});
}
}, {
text: ‘Reload Data‘,
handler: function() {
// Add a short delay to prevent fast sequential clicks
window.loadTask.delay(100, function() {
store1.loadData(generateData());
});
}
}],
items: chart
});
});
</script>
</head>
<body>
</body>
</html>[Ext JS 4] 实战之Chart 坐标控制(单坐标,双坐标),布布扣,bubuko.com
[Ext JS 4] 实战之Chart 坐标控制(单坐标,双坐标)
标签:des style class blog code java
原文地址:http://blog.csdn.net/oscar999/article/details/31787915