PDA

View Full Version : Ext.ux.chart (non-flash version,pure js)



cdj
2 Aug 2009, 7:21 PM
hi ~my friends
i'd like to share my extension,
there was a Ext.chart already available,but it goes along with the adobe flash.my solution is totally pure javascript(thanks to google iecanvas).so ~if you don't want use flash in application,you can use my extension instead.:>
wish you have interesting with it.:D
below is the constructor code:


Ext.ns("Ext.ux.chart");

/**
* @class Ext.ux.chart 图表控件基类
* @author cdj
* @version beta1.4.4
*/

Ext.ux.chart = Ext.extend(Ext.Component, {
/**
* @cfg 内框的高度
*/
width:300,
/**
* @cfg 内框的高度
*/
height:160,
/**
* @cfg 内框的间距,上右下左的顺序
*/
offsets:'5,40,5,5',
/**
* @cfg 基础css类
*/
baseCls:'ux-chart',
/**
* @cfg 边框的厚度
*/
borderWidth:1,
/**
* @cfg store
*/
store:{},
initComponent:function(){
Ext.ux.chart.superclass.initComponent.call(this);
this.addEvents(
//supported event list here
);
this.ds = this.store;
},

onRender:function(ct,pos){
this.preCreateSkeleton();
this.createSkeleton(ct,pos);
this.createXHandler();//behavior

this.romCVX.init();
this.ramCVX.init();
this.ds.on('load',this.onLoad,this);
},

/**
* 计算出用于构建图表结构的一些数据
*/
preCreateSkeleton:function(){
var _off = this.offsets.split(',');
Ext.applyIf(this,{
nOffset:Ext.isGecko?new Number(_off[0])+1:new Number(_off[0]),//火狐上有一点点偏差
eOffset:new Number(_off[1]),
sOffset:new Number(_off[2]),
wOffset:Ext.isGecko?new Number(_off[3])+7:new Number(_off[3])
});
this.chartHeight = this.height + this.sOffset + this.nOffset;//整个
this.chartWidth = this.width + this.wOffset + this.eOffset;

},

/**
* 创建图表文档元素的骨架,将几个文档元素都创建好
* @param ct 图表文档结构的容器
* @param pos
*/
createSkeleton:function(ct,pos){
var ramLayerId = Ext.id("","ui2-chart-ram-cvs-");
var romLayerId = Ext.id("","ui2-chart-rom-cvs-");
var labelLayerId = Ext.id("","ui2-chart-label-");//标签区
var evLayerId = Ext.id("","ui2-chart-ev-");//标签区
var tl = "position:absolute;left:0px;top:0px;";
this.style += "position:relative;";
var tpl = new Ext.XTemplate(
'<div>',
'<canvas id ='+romLayerId+' width = "'+this.chartWidth+'" height = "'+this.chartHeight+'" style='+tl+'background:'+this.bgColor+'></canvas>',//things that wouldn't be changed
'<div id = "'+labelLayerId+'" style = "position:absolute;left:0px;top:0px;"></div>',//标签文字区
'<canvas id ='+ramLayerId+' width = "'+this.chartWidth+'" height = "'+this.chartHeight+'" style='+tl+'></canvas>',//things that would be changed in run-time
'<div id = "'+evLayerId+'" style = "position:absolute;left:0px;top:0px;"></div>',//事件侦听区
'</div>'
);
this.el = tpl.append(ct,"",true);
if(this.baseCls){
this.el.addClass(this.baseCls);
}
if(this.cls){
this.el.addClass(this.cls);
}
if(this.id){
this.el.dom.id = this.el.id = this.id;
}
this.evct = Ext.get(evLayerId);
var ramCV = this.el.child("#"+ramLayerId,true);
this.lbct = Ext.get(labelLayerId);
var romCV = this.el.child("#"+romLayerId,true);
if(Ext.isIE){
ramCV = Ext.get(window.G_vmlCanvasManager.initElement(ramCV)).dom;
romCV = Ext.get(window.G_vmlCanvasManager.initElement(romCV)).dom;
}
this.ramCVX = ramCV.getContext('2d');
this.romCVX = romCV.getContext('2d');

},

/**
* rom层初始化方法 override it
*/
romLayerInitial:Ext.emptyFn,

/**
* ram层初始化方法 override it
*/
ramLayerInitial:Ext.emptyFn,

/**
* ram层画图方法 override it
*/
draw:Ext.emptyFn,

/**
* ram层重画方法 override it
*/
redraw:Ext.emptyFn,

createXHandler:function(){
Ext.applyIf(this,{
gridBgColor:this.colors.gridbg,
gridColor:this.colors.grid,
frameColor:this.colors.frame,
lineColor:this.colors.line
});

this.romCVX.init = this.romLayerInitial.createDelegate(this.romCVX,[this]);
delete this.romLayerInitial;

Ext.apply(this.ramCVX,{
init :this.ramLayerInitial.createDelegate(this.ramCVX,[this]),
draw :this.draw.createDelegate(this.ramCVX,[this]),
redraw:this.redraw.createDelegate(this.ramCVX,[this])
});

delete this.romLayerInitial;
delete this.draw;
delete this.redraw;
},

addLabel:function(conf){
var lbf = {};
Ext.apply(lbf,conf,{
id:Ext.id('','ui2-monitor-label-'),
position:[0,0],
tag:'span'
});
if(typeof lbf.style != "undefined"){
lbf.style += ";font-size:12px;white-space:nowrap";
}else {
lbf.style = "font-size:12px;white-space:nowrap";
}
if(typeof lbf.p == "undefined"){
lbf.p = lbf.position;
}
//下面的这个font-family害人啊,设置成‘宋体’ie上就不能竖排了
lbf.style += (";font-family:tahoma,arial,helvetica,sans-serif;position:absolute;left:"+lbf.p[0]+"px;top:"+lbf.p[1]+"px");
delete lbf.p;
delete lbf.position;
if(lbf.vmode){
lbf.style += ';writing-mode:tb-rl;';
delete lbf.vmode;
}

if(typeof lbf.background != "undefined"){
lbf.style += (";background:"+lbf.background);
}
var label = this.lbct.createChild(lbf,'',false);
return label;
},
getStore:function(){
return this.store;
},
/**
* override it
*/
onLoad:Ext.emptyFn
})

/**
* 直方图构造器
* @author cdj
* @usage:
* var histogram = new Ext.ux.chart.Histogram({
//renderTo:cdjel,
width:300,
height:200,
colSize:20,
gapSize:0.9,
_coloffset:30,
offsets:'10,0,80,10',
valueField:'value',
nameField:'name',
store:new Ext.data.SimpleStore({
fields:["name","value"],
autoLoad:true,
url:'res.json'
}),
colors:{
gridbg:'rgb(241,233,196)',
grid:'rgb(196,196,196)',
frame:'rgb(0,0,0)',
line:'rgb(0,0,0)'
},
yAxis:[{
text:'10K',
value:10*1024
},{
text:'1K',
value:1*1024
},{
text:'500bytes',
value:500
},{
text:'100bytes',
value:100
},{
text:'10bytes',
value:10
}]
});
*/
Ext.ux.chart.Histogram = Ext.extend(Ext.ux.chart, {
xfontSize:12,
gapScale:0.2,
colsLeftOffset:20,//初始位移
xTickTpl:"",
/**
* @cfg 颜色
*/
colors:{
gridbg:'rgb(241,233,196)',
grid:'rgb(196,196,196)',
frame:'rgb(0,0,0)',
line:'rgb(0,0,0)'
},

/**
* rom层初始化方法
*/
romLayerInitial:function(chart){
chart.xScale = (chart.width - 2*chart.borderWidth)/chart.xAxisN;
chart.yScale = (chart.height - 2*chart.borderWidth)/chart.yAxis.length;
this.save();
this.translate(chart.wOffset,chart.nOffset);
this.fillStyle = chart.gridBgColor;
this.fillRect(0,0,chart.width,chart.height);
this.fill();
this.strokeStyle = chart.frameColor;
this.moveTo(0,0);
this.lineTo(0,chart.height);
this.lineTo(chart.width,chart.height);
this.lineTo(chart.width,0);
this.lineTo(0,0);
this.stroke();
// draw the grid and ticks

this.strokeWidth = chart.borderWidth;//add by cj

this.strokeStyle = chart.gridColor;
var _p = [];// position for label
var _s;// scale for each tick
for(var i = 0;i < chart.yAxis.length;i++){
_s = i*chart.yScale;
this.moveTo(0,_s);
this.lineTo(chart.width+5,_s);// this '5' is the small line for tick
_p[0] = chart.chartWidth - chart.eOffset + 6; // this '4' is just for adjust the tick's position
_p[1] = _s +3;
chart.addLabel({
position:_p,
//vmode:true,
html:chart.yAxis[i].text
})
}
this.stroke();
//eof draw
},
ramLayerInitial:function(chart){
this.save();
this.translate(chart.wOffset,chart.nOffset);
this.lineStyle = chart.lineColor;
},
/**
* @override 重写onload
*/
onLoad:function(){
this.doDataConvert();
this.ramCVX.clearRect(0,0,10000,10000);
if(this.evct.first()){
var id = this.evct.id;
Ext.destroy(this.evct);//reconstruct evct layer
this.evct = Ext.DomHelper.append(this.el,{
id:id
},true);
}else {
//do nothing
}
this.ramCVX.draw();
Ext.ux.chart.Histogram.superclass.onLoad.call(this);
},
/**
* @private 数据转化
* 这里只是将column modal里的数据转化为用于渲染的数据
* 这个数据里不包含store数据衍生出的数据,比如每个列的高度(像素值)
* 因为出于效率的考虑,各列的像素值的计算还是放在draw方法的store遍历里比较好
*/
doDataConvert:function(){
this.pd = {};//用于构图的数据,data for paint
var sow = (this.width-this.colsLeftOffset)/this.ds.getCount();//self owned width

//calculate gapWidth
var gw = sow*this.gapScale;

//calculate every ColumnWidth
var cw = sow - gw;
var cols = [];
for(var i=0,cm = this.columnModal;i<cm.length;i++){
//Ext.log(cm[i].width)
var _tpl = new Ext.XTemplate(cm[i].tipTpl||"{"+cm[i].dataIndex+"}");
_tpl.compile();
var c = {
width:cm[i].width*cw,
tipTpl:_tpl,
dataIndex:cm[i].dataIndex,
color:cm[i].color || "#000"
//,color:"rgba()"
};
cols.push(c);
}
var _xpl = new Ext.XTemplate(this.xTickTpl);
_xpl.compile();
Ext.apply(this.pd,{
gapWidth:gw,
xTpl:_xpl,
selfOwnedWidth:sow,
columnsWidth:cw,
colCfgs:cols
})
},
/**
* @override 重写了画图方法
*/
draw:function(chart){
var pd = chart.pd;
var cf = pd.colCfgs;
this.beginPath();
this.save();
this.translate(chart.colsLeftOffset+chart.borderWidth,chart.borderWidth);
var parseColor = Ext.ux.chart.ColorManager.parseColor.createDelegate(Ext.ux.chart.ColorManager);
chart.ds.each(function(r,i){
var _off = 0;//前面的柱子的宽度总和
for(var ii = 0;ii<cf.length;ii++){

var _x = i*pd.selfOwnedWidth+_off;
var _y = chart.getYPixelByValue(r.get(cf[ii].dataIndex));
var _w = cf[ii].width;
var _h = chart.height-2*chart.borderWidth-_y;
var _clor = parseColor(cf[ii].color);
//begin render column
var gradient = this.createLinearGradient(_x,_y,_x+_w,_y);
gradient.addColorStop(0, _clor.s);
gradient.addColorStop(1, _clor.e);
this.fillStyle = gradient;
this.fillRect(_x,_y,_w,_h);
this.fill();

//发光区
var m = parseInt(cf[ii].width*0.5);
var gradient2 = this.createLinearGradient(_x+m,_y,_x+_w,_y);
gradient2.addColorStop(0, 'rgba(235,245,235,0.2)');
gradient2.addColorStop(1, 'rgba(235,245,235,0.6)');
this.fillStyle = gradient2;
this.fillRect(_x+m,_y,_w-m,_h);
this.fill();
//eof render column

//add tip
var _ev = chart.addBlankImage({
p:[chart.wOffset+chart.colsLeftOffset+_x,_y+chart.nOffset],
height:_h,
width:_w,
background:''
});
new Ext.ToolTip({
target: _ev,
title: cf[ii].title || pd.xTpl.apply(r.data),
width:200,
html: cf[ii].tipTpl.apply(r.data),
trackMouse:true
});
//eof add tip

_off += _w;
}//eof pd cols

var tx= i*pd.selfOwnedWidth+0.5*pd.columnsWidth;
//TODO 画标签
if(Ext.isGecko){
this.save();
this.fillStyle = chart.lineColor;
this.translate(tx-parseInt(chart.xfontSize/6),chart.height+5);
this.rotate(90 * Math.PI / 180);
this.mozTextStyle = chart.xfontSize+"px simsun";
this.mozDrawText(pd.xTpl.apply(r.data));
this.restore();
}else {
//ie
chart.addLabel({
html:pd.xTpl.apply(r.data),
p:[chart.colsLeftOffset + tx-parseInt(chart.xfontSize/6)+chart.wOffset,chart.height+chart.nOffset+5],
vmode:true
})
}
},this);
this.closePath();
this.stroke();
this.restore();
},
/**
* 清空所有重建
*/
reconstruct:function(config){
Ext.apply(this,config);
//clear up rom and ram layer
//this.ramCVX.restore();
this.ramCVX.restore();
//this.ramCVX.restore();
this.ramCVX.clearRect(0,0,10000,10000);

if(this.evct.first()){
var id = this.evct.id;
Ext.destroy(this.evct);//reconstruct evct layer
this.evct = Ext.DomHelper.append(this.el,{
id:id
},true);
}else {
//do nothing
}
this.romCVX.restore();
this.romCVX.clearRect(0,0,10000,10000);

if(this.lbct.first()){
var id = this.lbct.id;
Ext.destroy(this.lbct);//reconstruct evct layer
this.lbct = Ext.DomHelper.append(this.el,{
id:id
},true);
}else {
//do nothing
}
this.romCVX.init();
this.ramCVX.init();


},
/**
* 清空重画
*/
redraw:function(){
this.ramCVX.clearRect(0,0,10000,10000);
if(this.evct.first()){
var id = this.evct.id;
Ext.destroy(this.evct);//reconstruct evct layer
this.evct = Ext.DomHelper.append(this.el,{
id:id
},true);
}else {
//do nothing
}
this.ramCVX.draw();
},
/**
* @private
* @describe addBlankImage
*/
addBlankImage:function(conf){
var lbf = {};
Ext.apply(lbf,conf,{
position:[0,0],
src:Ext.BLANK_IMAGE_URL,
tag:'img',
width:10,
height:10
});
if(lbf.style){
lbf.style += ';font-size:12px;white-space:nowrap';
}else {
lbf.style = 'font-size:12px;white-space:nowrap';
}
if(!lbf.p){
lbf.p = lbf.position;
}
lbf.style += (";position:absolute;left:"+lbf.p[0]+"px;top:"+lbf.p[1]+"px;height:"+lbf.height+"px;width:"+lbf.width);
delete lbf.p;
delete lbf.position;
if(lbf.vmode){
lbf.style += ';writing-mode:tb-rl';
delete lbf.vmode;
}
if(lbf.background){
lbf.style += (";background:"+lbf.background);
}
var label = this.evct.createChild(lbf,'',false);
return label;
},
/**
* @private
* @describe 根据Y轴坐标的配置以及所传的值算出坐标位置
* @returns Y坐标值
*/
getYPixelByValue:function(v){
var max,min;
for(var i = 0;i < this.yAxis.length;i++){
if(v >= this.yAxis[i].value){
max = i==0?v:this.yAxis[i-1].value;
min = this.yAxis[i].value;
break;
}else {
continue;
}
}
var i = i-1;
if(typeof min == 'undefined'){
min = 0;
max = this.yAxis[i].value;
}
var result;
if(max == min){
result = 0;
}else{
result = (1-(v - min)/(max - min) + i)*this.yScale;
}
return result;
}
});

Ext.ux.chart.ColorManager = {
parseColor: function(str){

var result;

// rgb(num,num,num)
if((result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(str)))
return this.getColor(parseInt(result[1]), parseInt(result[2]), parseInt(result[3]));

// rgba(num,num,num,num)
if((result = /rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str)))
return this.getColor(parseInt(result[1]), parseInt(result[2]), parseInt(result[3]), parseFloat(result[4]));

// rgb(num%,num%,num%)
if((result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(str)))
return this.getColor(parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55);

// rgba(num%,num%,num%,num)
if((result = /rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str)))
return this.getColor(parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55, parseFloat(result[4]));

// #a0b1c2
if((result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(str)))
return this.getColor(parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16));

// #fff
if((result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(str)))
return this.getColor(parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16));

// Otherwise, we're most likely dealing with a named color.
var name = str.trim().toLowerCase();
if(name == 'transparent'){
return this.getColor(255, 255, 255, 0);
}
return ((result = this.colors[name])) ? this.getColor(result[0], result[1], result[2]) : false;
},
getColor: function(r, g, b, a){
this.rgba = ['r','g','b','a'];
var x = 4;
while(-1<--x){
this[this.rgba[x]] = arguments[x] || ((x==3) ? 1.0 : 0);
}
return this.normalize();
},
normalize: function(){
var limit = this.limit;
this.r = limit(parseInt(this.r), 0, 255);
this.g = limit(parseInt(this.g), 0, 255);
this.b = limit(parseInt(this.b), 0, 255);
this.a = limit(this.a, 0, 1);
return {s:"rgba("+this.r+","+this.g+","+this.b+","+this.a+")",e:"rgba("+this.r+","+this.g+","+this.b+","+(this.a-0.5)+")"};
//return "rgba("+this.r+","+this.g+","+this.b+","+this.a+")";
},
limit: function(val,minVal,maxVal){
return Math.max(Math.min(val, maxVal), minVal);
},
colors : {
aqua:[0,255,255],
azure:[240,255,255],
beige:[245,245,220],
black:[0,0,0],
blue:[0,0,255],
brown:[165,42,42],
cyan:[0,255,255],
darkblue:[0,0,139],
darkcyan:[0,139,139],
darkgrey:[169,169,169],
darkgreen:[0,100,0],
darkkhaki:[189,183,107],
darkmagenta:[139,0,139],
darkolivegreen:[85,107,47],
darkorange:[255,140,0],
darkorchid:[153,50,204],
darkred:[139,0,0],
darksalmon:[233,150,122],
darkviolet:[148,0,211],
fuchsia:[255,0,255],
gold:[255,215,0],
green:[0,128,0],
indigo:[75,0,130],
khaki:[240,230,140],
lightblue:[173,216,230],
lightcyan:[224,255,255],
lightgreen:[144,238,144],
lightgrey:[211,211,211],
lightpink:[255,182,193],
lightyellow:[255,255,224],
lime:[0,255,0],
magenta:[255,0,255],
maroon:[128,0,0],
navy:[0,0,128],
olive:[128,128,0],
orange:[255,165,0],
pink:[255,192,203],
purple:[128,0,128],
violet:[128,0,128],
red:[255,0,0],
silver:[192,192,192],
white:[255,255,255],
yellow:[255,255,0]
}
};
Ext.reg('ux-chart-histogram', Ext.ux.chart.Histogram);
and below is the usage example:



Ext.BLANK_IMAGE_URL = 'lib/ext/resources/images/default/s.gif';

Ext.onReady(function(){
//报表实验
//new a chart
var histogram = new Ext.ux.chart.Histogram({
width:700,
height:300,
//renderTo:cdjel,
offsets:'10,40,80,10',
store:new Ext.data.SimpleStore({
fields:["name","value1","value2"],
autoLoad:true,
url:'res.json'
}),
xTickTpl:"2009 年{name}",
columnModal:[{
dataIndex:'value1',
width:0.5,
tipTpl:"链路一流量是{value1}",
color:'olive'
//color:"rgba(0,0,0,1)"
},{
dataIndex:'value2',
//tipTpl:"链路二流量是{value1}",
//color:'purple',
width:0.2
},{
dataIndex:'value2',
width:0.3,
tipTpl:"链路三流量是{value2}",
color:'navy'
}],
colors:{
gridbg:'rgb(241,233,196)',
grid:'rgb(196,196,196)',
frame:'rgb(0,0,0)',
line:'rgb(0,0,0)'
},
yAxis:[{
text:'10K',
value:10*1024
},{
text:'1K',
value:1*1024
},{
text:'500bytes',
value:500
},{
text:'100bytes',
value:100
},{
text:'10bytes',
value:10
}],
listeners:{
render:function(){
//Ext.log("my chart rendered");
}
}
});


var win = new Ext.Window({
width:800,
height:460,
title:'测试图表',
items:[histogram]
})
win.show();

})

in this example,your data from the server should looked like this :


[
['一月','1020','100'],
['二月','300','500'],
['三月','500','200'],
['四月','200','400'],
['一月','200','700'],
['二月','300','100'],
['三月','500','600'],
['四月','1000','100']
]
there is a screenshot and a demo in the attachment.

to run this demo,you just need to take four steps.
1.download it.
2.decompress all files to the web application deployment folder(suppose you named"app").
your folder structure under the "app" should be :
/lib/mylib/excanvas.js
/lib/mylib/UI2.chart.Histogram.js
histogram.js
histogram.html
3.mkdir /lib/ext ,and copy the ext lib files to it
/lib/ext/resources/* (css and image files)
/lib/ext/ext-base.js
/lib/ext/ext-all.js
4.launch your server --> view the histogram.html.

you can modify my code as you wish, and use the modified code in your products.
notice that :
you must include the "google iecanvas" (which named excanvas.js) in your page,otherwise it won't work.
you can download it from my attachment or http://excanvas.sourceforge.net/


<!--[if IE]><script type="text/javascript" src="lib/mylib/excanvas.js"></script><![endif]-->
.its size is just 27k.

I'd appreciate comments and/or suggestions.

sorry for my broken english,i couldn't express my thinking very well,hope you could understand what i wrote:">

cdj
2 Aug 2009, 7:28 PM
同志们,帮忙顶顶帖子啊

lzhengkang
2 Aug 2009, 7:38 PM
大哥,很好,非常感谢!我正要学习这个!:D

cdj
2 Aug 2009, 7:41 PM
哈哈 ,谢谢哥们

Komes
3 Aug 2009, 5:24 AM
学感好链路二流量是 !!
的间

lxfliu
25 Oct 2009, 6:40 PM
真的不错

比用 Flash 强多了。

Scorpie
25 Oct 2009, 11:59 PM
Nice, looks alot like Ext Flot !

Matthias_WB
31 Oct 2009, 10:57 AM
Why the conversation is not in english??? Many people can read english posts, but smal count of people can understand chinese.

==============

為什麼對話是不是英文???很多人能夠閱讀英語的職位,而是狹數人能理解中國。

loverofdream
3 Nov 2009, 7:46 PM
兄弟,支持你

cdj
14 Nov 2009, 3:42 AM
真的不错

比用 Flash 强多了。

谢谢;)

cdj
14 Nov 2009, 3:47 AM
Nice, looks alot like Ext Flot !

yep,actually i use the same technology as Flotr does

cdj
14 Nov 2009, 4:00 AM
Why the conversation is not in english??? Many people can read english posts, but smal count of people can understand chinese.

==============

為什麼對話是不是英文???很多人能夠閱讀英語的職位,而是狹數人能理解中國。
:Dsorry ,my friend.i'm just poor in english.

BTW,1,300,000,000 is not a small count

cdj
14 Nov 2009, 4:14 AM
兄弟,支持你
谢谢

379548695
14 Dec 2009, 12:11 AM
呵呵。哥们我想知道2.x里面可以用吗?

zyzlsg
14 Dec 2009, 9:59 AM
好兄弟,谢了,你真的救了我一命啊,再次请教个问题,能不能让节点数据,直接显示,不用把鼠标移上去时才显示.谢谢

realjax
14 Dec 2009, 12:34 PM
I dunno..


It's all chinese to me.


:D

379548695
14 Dec 2009, 4:31 PM
谢谢
这个只有柱状图吗?还有其他的吗?:)

sexy22
11 Jan 2010, 9:38 PM
不错。。。

jarrednicholls
13 Jan 2010, 10:53 AM
BTW,1,300,000,000 is not a small count

Haha, that made me laugh...

eff844
30 Jan 2010, 4:32 AM
兄弟,,,关于 extjs 中flash chart 的帮助要在哪看?我很无助啊

我想在这种line chart 里显示观察线,,还要可以画一个小球进去,,,

唉......英文太差了

xiaotot
3 Feb 2010, 7:43 AM
CDJ果然很牛啊,写的好棒

ice42
10 Feb 2010, 7:35 PM
Why the conversation is not in english??? Many people can read english posts, but smal count of people can understand chinese.

==============

為什麼對話是不是英文???很多人能夠閱讀英語的職位,而是狹數人能理解中國。

Because were are chinese people.:)

ice42
10 Feb 2010, 7:39 PM
By the way,do not translation english to chinese via google.It is rubbish.:D

cdj
11 Mar 2010, 7:19 AM
呵呵。哥们我想知道2.x里面可以用吗?
可以的,我也发过一个2.0版的

cdj
11 Mar 2010, 7:20 AM
好兄弟,谢了,你真的救了我一命啊,再次请教个问题,能不能让节点数据,直接显示,不用把鼠标移上去时才显示.谢谢
可以的,不过要改下我的代码,需要的话我改一下给你

cdj
11 Mar 2010, 7:21 AM
这个只有柱状图吗?还有其他的吗?:)
最近比较忙,一直没写,Ext.ux.chart.Pie等还在待产阶段

cdj
11 Mar 2010, 7:22 AM
不错。。。
谢谢

cdj
11 Mar 2010, 7:23 AM
Haha, that made me laugh...
:D

cdj
11 Mar 2010, 7:24 AM
兄弟,,,关于 extjs 中flash chart 的帮助要在哪看?我很无助啊

我想在这种line chart 里显示观察线,,还要可以画一个小球进去,,,

唉......英文太差了
呵呵,自己写一个好了,你描述下你的需求,我可以用非flash的版本给你写

cdj
11 Mar 2010, 7:29 AM
CDJ果然很牛啊,写的好棒
谢谢谢谢

lj2008
27 Apr 2010, 11:27 PM
楼主好厉害啊,这个看起来相当不错,值得研究一下