javascript使用smipleChart实现简单图表
支持线性图区域图柱状图饼图
支持多浏览器
用到的是svg vml
<!DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.0Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<htmlxmlns="http://www.w3.org/1999/xhtml">
<head>
<metahttp-equiv="Content-Type"content="text/html;charset=utf-8"/>
<title>smipleChart</title>
<styletype="text/css">
.cc{
height:450px;width:800px;border:1pxsolid#999;position:relative;margin:20px;
}
</style>
</head>
<body>
<divid='t'></div>
<divid='t1'></div>
<divid='line'class="cc"></div>
<divid='area'class="cc"></div>
<divid='zhu'class="cc"></div>
<divid='zhu1'class="cc"style="height:600px;"></div>
<divid='segmentx'class="cc"></div>
<divid='segmenty'class="cc"></div>
<divid='pie'class="cc"></div>
<divid='pies'class="cc"></div>
<divid='vv'class="cc"style='height:300px;width:520px;'></div>
<scripttype="text/javascript">
(function(doc,undefined){
varwin =this,
uuuid =-1,
hasSVG =win.SVGAngle||doc.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1"),
isIE =/msie/i.test(navigator.userAgent)&&!win.opera,
path =hasSVG?'d':'path',
seal =hasSVG?'z':'e',
math =Math,
mathRound=math.round,
mathFloor=math.floor,
mathCeil =math.ceil,
mathMax =math.max,
mathMin =math.min,
mathAbs =math.abs,
mathCos =math.cos,
mathSin =math.sin,
M ='M',
L ='L';
win.$$=function(Id){
returndocument.getElementById(Id);
};
win.extend=function(){
vartarget=arguments[0]||{},i=1,length=arguments.length,deep=true,options;
if(typeoftarget==="boolean"){
deep=target;
target=arguments[1]||{};
i=2;
}
if(typeoftarget!=="object"&&Object.prototype.toString.call(target)!="[objectFunction]")
target={};
for(;i<length;i++){
if((options=arguments[i])!=null)
for(varnameinoptions){
varsrc=target[name],copy=options[name];
if(target===copy)
continue;
if(deep&©&&typeofcopy==="object"&&!copy.nodeType){
target[name]=arguments.callee(deep,src||(copy.length!=null?[]:{}),copy);
}
elseif(copy!==undefined)
target[name]=copy;
}
}
returntarget;
};
win.each= function(object,callback,args){
varname,i=0,length=object.length;
if(args){
args=Array.prototype.slice.call(arguments).slice(2);
if(length===undefined){
for(nameinobject)
if(callback.apply(object[name],[name,object[name]].concat(args))===false)
break;
}else
for(;i<length;i++)
if(callback.apply(object[i],[i,object[i]].concat(args))===false) //
break;
}else{
if(length===undefined){
for(nameinobject)
if(callback.call(object[name],name,object[name])===false)
break;
}else
for(varvalue=object[0];
i<length&&callback.call(value,i,value)!==false;value=object[++i]){}
}
returnobject;
};
win.contains=function(p,c){
if(!p||!c)returnfalse;
if(p===c)returntrue;
returnisIE
?p.contains(c)
:p.compareDocumentPosition(c)==20
?true
:false;
};
//---------------------------------------------------------------
functionprocessPoint(x){
returnisIE?~~x.toFixed(0):~~x.toFixed(0)+0.5;
};
functioncalTextLen(txt,cssStr){
varspan=doc.createElement('span');
if(cssStr){
typeofcssStr==='string'
?span.style.cssText=cssStr
:extend(span.style,cssStr);
}else{
extend(span.style,{
fontSiz :'12px',
fontFamily:'"LucidaGrande","LucidaSansUnicode",Verdana,Arial,Helvetica,sans-serif'
});
}
span.innerHTML=txt||'';
span.style.visibility='hidden';
doc.body.appendChild(span);
varwidth =span.offsetWidth,
height=span.offsetHeight;
doc.body.removeChild(span);
return{w:width,h:height};
};
functionangle(r,center,o,jingdu){
varhudu=Math.PI*2*(o/360),
x=center[0]+r*Math.sin(hudu),
y=center[1]+-r*Math.cos(hudu);
return[x.toFixed(jingdu||0),y.toFixed(jingdu||0)];
}
functionxx(a,b,lineNum){
vart =1000,
stf=((b*t-a*t)/lineNum)/t,
arr=[1,2,2.5,5,10],
c =1,
v;
// 分割线的基数是 [1,2,2.5,5,10]这个步骤是查找间隔属于哪个范围
if(stf<arr[0]){
while(stf<arr[0]){
c=c*10;
arr[0]=arr[0]/c;
}
each([1,2,2.5,5,10],function(i,o){
arr[i]=o/c;
});
}elseif(stf>arr[4]){
while(stf>arr[4]){
c=c*10;
arr[4]=arr[4]*c;
}
each([1,2,2.5,5,10],function(i,o){
arr[i]=o*c;
});
}
//上面找到间隔后找到间隔中最接近的一个
each(arr,function(i,o){
if(stf<=o){
v=o;
returnfalse;
}
});
varbj =(mathAbs(a)*t)/(v*t),
ba =0,
isZ=bj!==parseInt(bj);
isZ
&&a>0
?ba=-a%v*t
:ba=(mathAbs(a)%v-v)*t;
a=(a*t+ba)/t;
b=(b*t+(b%v===0?0:(v-b%v))*t)/t;
//看看还剩几条线没有画
varnum=Math.max(0,lineNum-Math.round((b-a)/v));
if(a>=0){
//坐标比较整数化
if(a!=0&&num!=0&&a%10!==0){
while(a!=0&&num!=0){
a=(a*t-v*t)/t;
num--;
if((a*t-v*num*t)/10000>0&&a%10===0)
break;
}
}
if(num!=0){
while(num!==0){
b=(b*t+v*t)/t
num--;
}
}
}else{
//坐标比较整数化
if(b<0&&num!=0){
while(b!=0&&num!=0&&b%10!==0){
b=(b*t+v*t)/t;
num--;
if((b*t+v*num*t)/t<0&&b%10===0)
break;
}
}
if(num!=0){
while(num!==0){
a=(a*t-v*t)/t
num--;
}
}
}
return{min:a,max:b,stf:v};
}
//---------------------------------------------------------------------------------------------------------------
//对svgvml元素的一些创建修改属性样式删除== 一些的操作
win.vector=function(){};
vector.prototype={
$c:function(graphic,nodeName){
this.element=this[0]=doc.createElementNS('http://www.w3.org/2000/svg',nodeName);
this.graphic=graphic;
returnthis;
},
attr: function(hash,val){
varelem =this.element,
key,
value;
if(typeofhash==='string'){
if(val===undefined){
returnelem.getAttribute(hash);
}else{
elem.setAttribute(hash,val);
returnthis;
}
}else{
for(keyinhash){
value=hash[key];
if(key===path){
value&&value.join
&&(value=value.join(''));
/(NaN| |^$)/.test(value)
&&(value='M00');
}
elem.setAttribute(key,value)
}
}
returnthis;
},
css: function(hash){
for(varkeyinhash){
isIE&&key=="opacity"
?this[0].style['filter']="alpha(opacity="+hash[key]*100+")"
:this[0].style[key]=hash[key];
}
returnthis;
},
on:function(eventName,handler){
varself=this;
/*this.element.addEventListener(eventName,function(){
handler.call(self)
},false);*/
this.element['on'+eventName]=function(e){
e=e||win.event;
handler.call(self,e);
}
returnthis;
},
appendTo: function(parent){
if(parent){
parent.element
?parent.element.appendChild(this.element)
:parent.appendChild(this.element)
}else{
this.graphic.container.appendChild(this.element);
}
returnthis;
},
addText:function(str){
varelem=this.element;
if(elem.nodeName==='text'){
elem.appendChild(doc.createTextNode(str+''));
}
returnthis;
},
setOpacity:function(v){
this.attr('fill-opacity',v);
returnthis;
},
setSize:function(v){
this[0].nodeName==='circle'
?this.attr('r',4+(v===0?0:2))
:this.attr({'stroke-width':v});
returnthis;
},
toFront:function(){
this[0].parentNode.appendChild(this[0]);
returnthis;
},
show: function(){
this[0].style.display='block';
returnthis;
},
hide: function(){
this[0].style.display='none';
returnthis;
},
destroy:function(){
//销毁节点......................
varnode=this[0]||this;
node.onmouseover=node.onmouseout=node.onclick=null;
node.parentNode
&&node.parentNode.removeChild(node);
returnthis;
}
};
//---------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
//如果是vml修改其中的一些方法
if(!hasSVG){
//-------------创建vml环境-----------------
doc.createStyleSheet().addRule(".vml","behavior:url(#default#VML);display:inline-block;position:absolute;left:0px;top:0px");
!doc.namespaces.vml&&!+"\v1";
doc.namespaces.add("vml","urn:schemas-microsoft-com:vml");
//-------------修改一些方法-----------------
extend(vector.prototype,{
$c:function(graphic,nodeName){
varname=nodeName||'shape';
this.element=this[0]=(name==='div'||name==='span')
?doc.createElement(name)
:doc.createElement('<vml:'+name+'class="vml">');
this.graphic=graphic;
returnthis;
},
/*on:function(eventName,handler){
varself=this;
this.element.attachEvent("on"+eventName,function(){
handler.call(self);
});
returnthis;
},*/
addText:function(txt){
this[0].innerHTML=txt||'';
returnthis;
},
setSize:function(v){
this[0].strokeWeight=v;
returnthis;
},
setOpacity:function(v){
this.opacity.opacity=v;
returnthis;
}
});
}
//---------------------------------------------------------------------------------------------------
//画图类
//------------------------------------------------------------
win.smipleChart=function(){
this.init.apply(this,arguments);
};
smipleChart.list =[];
smipleChart.timer =null;
smipleChart.lazyLoad =function(id){
id =id||'0'
smipleChart.list[id]
&&smipleChart.list[id].loadMe();
};
smipleChart.prototype={
options:{
charts:{
paddingRight:20,
radius:200,
style :{
fontFamily:'"LucidaGrande","LucidaSansUnicode",Verdana,Arial,Helvetica,sans-serif',
fontSize :'12px',
background:'#FFFFFF'
}
},
title:{
text :'',
y :10,
style:{
fontFamily:'Verdana,Arial,Helvetica,sans-serif',
fontSize:'16px',
fontWeight:'bold'
}
},
subTitle:{
text :'',
y :30,
style :{
fontFamily:'Verdana,Arial,Helvetica,sans-serif',
fontSize:'12px',
color:'#111'
}
},
yUnit:{
text :'',
style:{
fontFamily:'Verdana,Arial,Helvetica,sans-serif',
fontSize:'12px',
color:'#111'
},
lineNum:10
}
},
init:function(container,options){
clearTimeout(smipleChart.timer)
varself =this;
this.width =container.offsetWidth;
this.height =container.offsetHeight;
this.currList={};
this.uuuid =++uuuid;
this.timer =null;
//主要画图组的集合形式
//{id:{dom:xx,show:true}}
this.mainGroup={};
//分段的时候要用到的 知道哪些是隐藏了的 因为要涉及到重绘
this.hideList ={};
//svg里面画图必须有一个svg标签vml就用div了
this.container=hasSVG
?newvector().$c(1,'svg')
.attr({
xmlns :'http://www.w3.org/2000/svg',
version:'1.1',
width:this.width,
height:this.height
})
.css({fontSize:'12px'})
.appendTo(container)
:newvector().$c(1,'div')
.css({
fontSize:'12px',
width :this.width+'px',
height :this.height+'px'
})
.appendTo(container);
this.loading=container.appendChild(doc.createElement('img'));
this.loading.setAttribute('src','http://images.cnblogs.com/cnblogs_com/wtcsy/192373/r_loading.gif');
this.loading.style.position='absolute';
this.loading.style.top =container.offsetHeight/2-this.loading.offsetHeight/2+'px';
this.loading.style.left=container.offsetWidth/2-this.loading.offsetWidth/2+'px';
varc =extend(true,{},this.options),
opts =this.opts=extend(true,c,options),
style=extend(opts.charts.style,{
width :this.width,
height:this.height
});
smipleChart.list[this.uuuid]=this;
smipleChart.timer=setTimeout(function(){
smipleChart.lazyLoad();
},200);
},
loadMe:function(){
varopts =this.opts,
self =this,
type =opts.charts.type;
this.container=this.container
.on('mouseout',function(e){
varelem=e.relatedTarget||e.toElement;
if(!contains(this[0],elem)){
self.hideTooltip();
self.currList.dot
&&self.currList.dot.setSize(0);
self.currList.line
&&self.currList.line.setSize(1.5);
self.currList={};
}
})
.css({display:'none'})[0];
//计算绘画盘子的时候需要的一些参数
this.getDrawArea()
.createTooltip() //创建提示信息的框框
.drawTitle() //画标题
//画盘子
'line,area,pie'.indexOf(type)>=0
&&(opts.charts.panel='x');
'pie,pies'.indexOf(type)<0
&&this.drawPanel();
this.drawLegend(opts.legend.type); //画色块条
vartype={
line :'drawLine',
area :'drawArea',
columns:'drawColumns',
pie :'drawPie',
pies :'drawPies',
segment:'drawSegment'
}[opts.charts.type];
//开始画图..............
this[type]();
//删除节点
this.loading.parentNode.removeChild(this.loading);
//断开引用
this.loading=null;
this.container.style.display='';
setTimeout(function(){
smipleChart.lazyLoad((++self.uuuid)+'');
},10)
},
createElement:function(nodeName){
returnnewvector().$c(this,nodeName);
},
group:function(name){
returnthis.createElement(hasSVG?'g':'div').attr('mark',name);
},
getDrawArea:function(){
varopts =this.opts,
width =this.width,
height =this.height,
title =opts.title,
subTitle=opts.subTitle,
area ={
//去掉坐标轴左边的刻度文本宽度(预估)80为定值左边只留80的间距
areaWidth :width-80,
//去掉坐标轴底下的文本和标线的高度
areaHeight:height-40,
//原点的X位置 下面会计算到
startX:0,
//原点的Y位置 下面会计算到
startY:0,
//中心的x坐标画饼图的时候需要知道圆心的位置
centerX:0,
//中心的y坐标画饼图的时候需要知道圆心的位置
centerY:0
};
//如果主标题存在减去主标题的高度否则减去10的高
area.areaHeight-=(title.text!=='')
?title.y
:10;
//去掉副标题高度
area.areaHeight-=(subTitle.text!=='')
?subTitle.y
:10
area.startX=80;
area.startY=height-40;
//圆心的位置
area.centerX=width/2;
area.centerY=height/2;
//右边留一些空隙
area.areaWidth-=20;
//上边也留一些间距
area.areaHeight-=15;
opts.area=area;
returnthis;
},
drawTitle:function(){
varopts =this.opts,
self =this,
arr =[opts.title,opts.subTitle,opts.yUnit],
//3个标题坐标的位置的基本参数
config=[
{
x:this.width/2,
y:opts.title.y
},
{
x:this.width/2,
y:opts.subTitle.y
},
{
x:opts.yUnit.x,
y:this.height/2-20
}
],
tpanel=this.group('title')
.appendTo();
each(arr,function(i,title){
vartext=title.text;
if(text){
varelem=self.baseDraw.span(self,{
'text-anchor':'left',
x:mathMax(config[i].x-calTextLen(text,title.style).w/2,10),
y:config[i].y
},calTextLen(title.text,title.style).h)
.css(title.style)
.addText(text)
.appendTo(tpanel);
//如果为2的时候就说明是副标题 将它竖过来
if(i===2){
hasSVG
?elem.attr({transform:'rotate(270,'+(opts.yUnit.x+10)+','+self.height/2+')'})
:(elem.element.style.filter='progid:DXImageTransform.Microsoft.BasicImage(rotation=3)')
}
}
});
returnthis;
},
//画盘子 比较麻烦
drawPanel:function(type){
var opts=this.opts,
self=this,
area=opts.area,
chartsType=opts.charts.type,
isSegment =chartsType==='segment',
//盘子的类型是横盘子还是纵盘子
type=opts.charts.panel||'x';
//底板
vardrawAreaWidth =area.areaWidth,
drawAreaHeight=area.areaHeight,
//原点的坐标
startX=area.startX,
startY=area.startY;
varallData =[],
minValue=0,
maxValue=10,
//线的条数只能在1到10之间
lineNum =mathMin(10,mathMax(opts.yUnit.lineNum,1)),
staff;
//组合所有的数据
each(opts.chartData,function(i,o){
//如果是柱状图是对所有的数据求和
isSegment
?each(o.data,function(j,d){
allData[j]
?allData[j]=allData[j]+(~~d)
:allData[j]=~~d;
})
:allData=allData.concat(o.data)
});
//给所有的数据排序 为了下面求最大值最小值
allData.sort(function(a,b){returna-b});
//求出最大值最小值
maxValue=allData[allData.length-1];
each(allData,function(i,o){
if(o!==null){
minValue=o;
returnfalse;
}
});
//主盘子容器
varpanel=this.group('panel').appendTo();
varresult=xx(minValue,maxValue,lineNum),
min =result.min,
max =result.max,
f =result.stf;
isSegment
&&(min=0);
//表示画的是横坐标或者是双坐标
if(type.toLowerCase()==='x'){
//横坐标单位间隔
var xPices=drawAreaWidth/opts.xUnit.units.length,
//单位间隔的中心点
offset=xPices/2,
yPices=drawAreaHeight/lineNum;
//--------------------------------画横向的点和文字---------------------------------------------------------
vary=hasSVG?5:10,
t=1000,
span;
each(opts.xUnit.units,function(i,d){
self.baseDraw.path(self,{
border :1,
borderColor:'#C0C0C0',
isfill :false,
path :[
M,
processPoint(startX+(i*xPices)),
processPoint(startY),
L,
processPoint(startX+(i*xPices)),
processPoint(startY+5)
]
}).
appendTo(panel);
span=self.baseDraw.span(self,{
x :startX+offset+(i*xPices),
y :startY+y,
'text-anchor':'middle'
})
.css({
fontFamily:'Verdana,Arial,Helvetica,sans-serif',
fontSize :'12px'
})
.addText(opts.xUnit.units[i])
.appendTo(panel)[0];
!hasSVG
&&(span.style.left=parseInt(span.style.left)-span.offsetWidth/2+'px');
});
//--------------------------------画纵向的点和文字-----------------------------------------------------------------------
for(i=0;i<=lineNum;i++){
self.baseDraw.path(self,{
border :1,
borderColor:'#C0C0C0',
isfill :false,
path :[M,startX,processPoint(startY-(i*yPices)),L,processPoint(startX+drawAreaWidth),processPoint(startY-(i*yPices))]
})
.css({zIndex:-10})
.appendTo(panel);
varspan=self.baseDraw.span(self,{
x:startX-15,
y:startY-i*yPices-calTextLen(min+i*f+'').h/2,
'text-anchor':'middle'
})
.css({
'font-family':'Verdana,Arial,Helvetica,sans-serif',
'font-size' :'12px',
width :'40px',
display :'block',
textAlign :'right'
})
.addText((min*t+(i*t*f/t)*t)/t+'')
.appendTo(panel)[0];
if(!hasSVG){
span.style.top =parseInt(span.style.top)+span.offsetHeight/2-5+'px';
span.style.left=parseInt(span.style.left)-35+'px'
}
}
}else{
//横坐标单位间隔
var yPices=drawAreaHeight/(opts.xUnit.units.length),
//单位间隔的中心点
offset=Math.round(yPices/2),
x =hasSVG?25:70,
y =hasSVG?0:5,
span
each(opts.xUnit.units,function(i,d){
self.baseDraw.path(self,{
border :1,
borderColor:'#C0C0C0',
isfill :false,
path :[
M,
processPoint(startX-5),
processPoint(startY-i*yPices),
L,
processPoint(startX),
processPoint(startY-i*yPices),
]
})
.appendTo(panel);
span=self.baseDraw.span(self,{
x :startX-x,
y :startY-i*yPices-offset-calTextLen(d).h/2+y,
'text-anchor':'middle'
})
.css({
fontFamily:'Verdana,Arial,Helvetica,sans-serif',
fontSize:'12px',
width :'60px',
textAlign:'right'
})
.addText(d)
.appendTo(panel)
});
varxPices=drawAreaWidth/lineNum;
for(vari=0;i<=lineNum;i++){
self.baseDraw.path(self,{
border :1,
borderColor:'#C0C0C0',
isfill :false,
path :[
M,
processPoint(startX+(i*xPices)),
processPoint(startY),
L,
processPoint(startX+(i*xPices)),
processPoint(startY-drawAreaHeight)
]
}).
appendTo(panel);
self.baseDraw.span(self,{
x :startX-calTextLen(min+i*f+'').w/2+i*xPices,
y :startY,
'text-anchor':'left'
})
.css({
fontFamily:'Verdana,Arial,Helvetica,sans-serif',
fontSize:'12px'
})
.addText(min+i*f+'')
.appendTo(panel);
}
}
//-----------------------------------------------------------------------------------------------------
//因为起点很可能不是从0开始的 所以在起点的时候要要加上到0那部分的值
varjianju=0;
if(min>0)jianju=min;
if(max<0)jianju=max;
startX=opts.charts.panel==='x'?startX:startX-xPices*(min/f);
startY=opts.charts.panel==='x'?startY+yPices*(min/f):startY;
opts.draw={
startX :startX, //X轴起点
startY :startY, //Y轴起点
xPices :xPices, //X轴每份的宽度
yPices :yPices, //Y轴每份的宽度
offset :offset, //X单分中心点位置偏移量
jianjuY:jianju*yPices/f,
jianjuX:jianju*xPices/f,
feed :f //Y轴的每份有多少
}
returnthis;
},
createTooltip:function(){
//一个组
this.tipC=this.group('tip')
.css({zIndex:200,height:'20px',width:'20px',position:'absolute'})
.appendTo()
.hide()
//画一个框框baseDraw
this.tipBox=this.baseDraw.rect(this,{arc:0.22,fill:'#fff',border:2,borderColor:'#606060'})
.appendTo(this.tipC)
//因为svg里面的g可以直接定位但是vml里面的group渲染很慢所以改div 所以这里的父不一洋
varp=isIE?this.tipBox:this.tipC;
this.tipTxtContainer=this.baseDraw.text(this,{fill:'#000000',x:5,y:19,'text-anchor':'left'})
.css({
fontFamily:'Verdana,Arial,Helvetica,sans-serif',
fontSize:'12px',
background:'#FFF'
})
.appendTo(p);
this.tipText=doc.createTextNode('');
this.tipTxtContainer[0].appendChild(this.tipText);
returnthis;
},
showTooltip:function(obj,x,y,data){
/*vartxt =obj.name+':'+data,
size=calTextLen(txt,this.tipTxtContainer[0].style.cssText),
pos ={x:x-(size.w+5*2)/2,y:y-32};
this.tipC
.toFront()
.show();
if(hasSVG){
this.tipC.attr({transform:'translate('+pos.x+','+pos.y+')'});
this.tipBox
.attr({width :size.w+5*2,height:size.h+5*2,stroke:obj.color||'#606060'});
}else{
this.tipC.css({left:pos.x,top:pos.y});
this.tipBox
.css({width:size.w+5*2,height:size.h+5*2})
this.tipBox[0].strokeColor=obj.color||'#000';
}
this.tipText.nodeValue=txt||'';*/
clearTimeout(this.timer);
vartxt =obj.name+':'+data,
self=this,
size=calTextLen(txt,this.tipTxtContainer[0].style.cssText),
pos ={x:x-(size.w+5*2)/2,y:y-32};
if(hasSVG){
self.tipBox
.attr({width :size.w+5*2,height:size.h+5*2,stroke:obj.color||'#606060'});
}else{
self.tipBox
.css({width:size.w+5*2,height:size.h+5*2})
self.tipBox[0].strokeColor=obj.color||'#000';
}
this.tipText.nodeValue=txt||'';
if(this.tipC[0].style.display==='none'){
hasSVG
?self.tipC.attr({transform:'translate('+pos.x+','+pos.y+')',pos:pos.x+'-'+pos.y})
:self.tipC.attr({pos:pos.x+'-'+pos.y}).css({left:pos.x,top:pos.y});
this.tipC
.toFront()
.show();
}else{
varmove=function(t,b,c,d){
returnc*(t/=d)*t+b;
},
t=0,
b=self.tipC.attr('pos').split('-'),
c=[pos.x,pos.y],
d=5;
this.timer=setInterval(function(){
if(t<d){
t++;
varx=move(t,~~b[0],(~~c[0])-(~~b[0]),d),
y=move(t,~~b[1],(~~c[1])-(~~b[1]),d);
hasSVG
?self.tipC.attr({transform:'translate('+x+','+y+')',pos:x+'-'+y})
:self.tipC.attr({pos:x+'-'+y}).css({left:x,top:y});
}else{
clearTimeout(self.timer);
}
},1);
};
},
hideTooltip:function(){
this.tipC.hide();
},
drawLegend:function(type,redraw){
varself =this,
opts =this.opts,
isLine=opts.charts.type==='line',
//颜色块的大小
t_width =20,
t_height=20,
//块之间的距离
t_space =5,
datas =opts.chartData,
len =datas.length,
css =opts.legend.style,
//最大长度如果是纵着的需要最大的长度
maxWidth=10,
maxHeight=30,
//这个东西的位置
orig_pos=opts.legend.pos?opts.legend.pos:[2,2],
//显示隐藏组的函数
handle =function(i){
varg=self.mainGroup['chart'+i],
issegment=opts.charts.type==='segment';
if(g.show){
g.chart.hide();
g.show=false;
hasSVG
?this.attr({fill:'#ccc'})
:this[0].style.color='#ccc';
//如果是分段图 是会涉及到重画的
if(issegment){
self.hideList[i]='';
varmainGroup=self.mainGroup;
for(varnameinmainGroup){
varparent=mainGroup[name].chart,
nodes =parent[0].childNodes,
len =nodes.length;
//销毁图上面画的东西
for(vari=len-1;i>=0;i--){
vector.prototype.destroy.call(nodes[i])
}
}
//重画
self.drawSegment();
}
}else{
g.chart.show();
g.show=true;
hasSVG
?this.attr({fill:'#000'})
:this[0].style.color='#000'
if(issegment){
deleteself.hideList[i];
varmainGroup=self.mainGroup;
for(varnameinmainGroup){
varparent=mainGroup[name].chart,
nodes =parent[0].childNodes,
len =nodes.length;
for(vari=len-1;i>=0;i--){
vector.prototype.destroy.call(nodes[i])
}
}
self.drawSegment();
}
}
},
arr=[];
type=type||'lateral';
varlegendPanel=self.group('Legend')
.appendTo();
if(type==='lateral'){
//如果是横着的
vartop =orig_pos[1]+5,
th =hasSVG?0:3,
left=orig_pos[0]+5;
each(datas,function(i,d){
left=i===0?left:t_space+left;
//计算所有left的位置
//如果是线性图 按线性图的方式画图
if(isLine){
self.baseDraw.path(self,{
border :1.5,
borderColor:d.color,
isfill :false,
path :[
M,
left.toFixed(0),
(top+10).toFixed(0),
L,
(left+25).toFixed(0),
(top+10).toFixed(0)
]
})
.appendTo(legendPanel);
self.baseDraw[d.dotType||'circle'](self,{
x:left+12,
y:top+10,
r:4,
fillColor:d.color
})
.appendTo(legendPanel);
}else{
self.baseDraw.rect(self,{
arc :0.1,
fill :d.color,
border :1,
borderColor:d.color,
left :left,
top :top,
width :t_width+'px',
height :t_height+'px'
})
.appendTo(legendPanel)
}
left=left+t_width+2+t_space;
varw=calTextLen(d.name,css).w
self.baseDraw.span(self,{
'text-anchor':'left',
x:left,
y:top+th
})
.css(extend(css,{cursor:'pointer'}))
.on('click',function(){
handle.call(this,i);
})
.addText(d.name)
.appendTo(legendPanel);
left=left+w;
});
this.baseDraw.rect(this,{
arc :0.1,
fill :'none',
border :1.5,
borderColor:'#666666',
width :left+t_space-orig_pos[0],
height :maxHeight,
left :orig_pos[0],
top :orig_pos[1]
})
.appendTo(legendPanel);
}else{
vartop =orig_pos[1]+5,
th =hasSVG?0:3,
left=orig_pos[0]+5;
each(datas,function(i,d){
top=i===0?top:t_space+top;
self.baseDraw.rect(self,{
arc :0.1,
fill :d.color,
border :1,
borderColor:d.color,
left :left,
top :top,
width :t_width+'px',
height :t_height+'px'
})
.appendTo(legendPanel);
varh=calTextLen(d.name,css).h;
self.baseDraw.span(self,{
'text-anchor':'left',
x:left+t_width+2+t_space,
y:top+th
})
.css(extend(css,{cursor:'pointer'}))
.addText(d.name)
.on('click',function(){
//如果是多层饼图不行进隐藏
if(opts.charts.type==='pies')return;
handle.call(this,i);
})
.appendTo(legendPanel);
top=top+h+t_space;
maxWidth=Math.max(maxWidth,calTextLen(d.name,css).w);
});
this.baseDraw.rect(this,{
arc :0.1,
fill :'none',
border :1.5,
borderColor:'#666666',
width :maxWidth+22+15,
height :top+t_space-orig_pos[1],
left :orig_pos[0],
top :orig_pos[1]
})
.appendTo(legendPanel);
}
returnthis;
},
drawLine :function(){
varself=this,
opts=this.opts,
draw=opts.draw;
each(opts.chartData,function(i,o){
varid='chart'+i,
lineGroup=self.group(id)
.appendTo();
self.mainGroup[id]={
chart:lineGroup,
show :true
};
varpath=[M],
data=o.data,
line;
for(vari=0,l=data.length;i<l;i++){
if(data[i]==null){
//如果这个数据不存在并且不是第一个数据路径上加M
if(path[path.length-1]!==M)
path.push(M);
}else{
//如果不是第一个数据路径添加L
i!==0&&path.push("L");
//如果前面一个是null并且不是第一个 把那个L去掉
if(i>0&&data[i-1]==null)
path.pop();
//计算出点的x,y的位置
varx=draw.startX+draw.offset+(i*draw.xPices),
y=draw.startY-data[i]*(draw.yPices/draw.feed);
if(isIE){
x=parseInt(x);
y=parseInt(y);
}
path.push(x);
path.push(y);
//画点
vardotType=o.dotType||'circle';
self.baseDraw[dotType](self,{
x:x,