Support linear graph area graph histogram pie chart
Supports multiple browsers
Used svg vml
The code copy is as follows:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>smipleChart</title>
<style type="text/css">
.cc{
height:450px; width:800px; border:1px solid #999; position:relative; margin:20px;
}
</style>
</head>
<body>
<div id='t'></div>
<div id='t1'></div>
<div id='line'></div>
<div id='area'></div>
<div id='zhu'></div>
<div id='zhu1' style="height:600px;"></div>
<div id='segmentx'></div>
<div id='segmenty'></div>
<div id='pie'></div>
<div id='pies'></div>
<div id='vv' style='height:300px; width:520px;'></div>
<script type="text/javascript">
(function(doc,undefined){
var win = 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){
return document.getElementById(Id);
};
win.extend = function(){
var target = arguments[0] || {}, i = 1, length = arguments.length, deep = true, options;
if ( typeof target === "boolean" ) {
deep = target;
target = arguments[1] || {};
i = 2;
}
if ( typeof target !== "object" && Object.prototype.toString.call(target)!="[object Function]")
target = {};
for(;i<length;i++){
if ( (options = arguments[ i ]) != null )
for(var name in options){
var src = target[ name ], copy = options[ name ];
if ( target === copy )
continue;
if ( deep && copy && typeof copy === "object" && !copy.nodeType ){
target[ name ] = arguments.callee( deep, src || ( copy.length != null ? [ ] : { } ), copy );
}
else if(copy !== undefined)
target[ name ] = copy;
}
}
return target;
};
win.each = function ( object, callback, args ) {
var name, i = 0, length = object.length;
if ( args ) {
args = Array.prototype.slice.call(arguments).slice(2);
if ( length === undefined ) {
for ( name in object )
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 ( name in object )
if ( callback.call( object[ name ], name, object[ name ] ) === false )
break;
} else
for ( var value = object[0];
i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
}
return object;
};
win.contains = function(p,c){
if(!p||!c)return false;
if(p===c)return true;
return isIE
? p.contains(c)
: p.compareDocumentPosition(c)==20
? true
: false;
};
//---------------------------------------------------------------
function processPoint( x ){
return isIE ? ~~x.toFixed(0) : ~~x.toFixed(0) + 0.5;
};
function calTextLen(txt, cssStr){
var span = doc.createElement('span');
if(cssStr){
typeof cssStr === 'string'
? span.style.cssText = cssStr
: extend(span.style,cssStr);
}else{
extend(span.style,{
fontSiz: '12px',
fontFamily : '"Lucida Grande", "Lucida Sans Unicode", Verdana, Arial, Helvetica, sans-serif'
});
}
span.innerHTML = txt || '';
span.style.visibility = 'hidden';
doc.body.appendChild(span);
var width = span.offsetWidth,
height = span.offsetHeight;
doc.body.removeChild(span);
return {w:width,h:height};
};
function angle(r,center,o,jingdu){
var hudu = 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)];
}
function xx(a,b,lineNum){
var t = 1000,
stf = ((b*ta*t)/lineNum)/t,
arr = [1,2,2.5,5,10],
c = 1,
v;
// The cardinality of the dividing line is [1, 2, 2.5, 5, 10] This step is to find out which range the interval belongs to
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;
});
}else if(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;
});
}
//Follow the interval to find the closest one in the interval
each(arr,function(i,o){
if(stf<=o){
v = o;
return false;
}
});
var bj = (mathAbs(a)*t)/(v*t),
ba = 0,
isZ = bj!==parseInt(bj);
isZ
&&a>0
? ba = -a%v*t
: ba = (mathAbs(a)%vv)*t;
a = (a*t+ba)/t;
b = (b*t+(b%v===0?0:(vb%v))*t)/t;
//Look at how many lines are left and not drawn
var num = Math.max(0,lineNum - Math.round((ba)/v));
if(a>=0){
//Coordinate comparison integer
if(a!=0&&num!=0&&a%10!==0){
while(a!=0&&num!=0){
a = (a*tv*t)/t;
num--;
if((a*tv*num*t)/10000>0&&a%10===0)
break;
}
}
if(num!=0){
while(num!==0){
b = (b*t+v*t)/t
num--;
}
}
}else{
//Coordinate comparison integer
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*tv*t)/t
num--;
}
}
}
return {min:a,max:b,stf:v};
}
//---------------------------------------------------------------------------------------------------------------
//Create some creations of svg vml elements and delete attribute styles == some operations
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;
return this;
},
attr:function(hash,val){
var elem = this.element,
key,
value;
if(typeof hash === 'string'){
if(val === undefined){
return elem.getAttribute(hash);
}else{
elem.setAttribute(hash, val);
return this;
}
} else {
for(key in hash){
value = hash[key];
if(key === path){
value && value.join
&&(value = value.join(' '));
/(NaN| |^$)/.test(value)
&&(value = 'M 0 0');
}
elem.setAttribute(key, value)
}
}
return this;
},
css: function(hash){
for(var key in hash){
isIE && key == "opacity"
? this[0].style['filter'] = "alpha(opacity="+ hash[key] * 100+")"
: this[0].style[key] = hash[key];
}
return this;
},
on: function(eventName, handler){
var self = this;
/*this.element.addEventListener(eventName,function(){
handler.call(self)
},false);*/
this.element['on' + eventName] = function(e){
e = e || win.event;
handler.call(self,e);
}
return this;
},
appendTo:function(parent){
if(parent){
parent.element
? parent.element.appendChild(this.element)
: parent.appendChild(this.element)
} else {
this.graphic.container.appendChild(this.element);
}
return this;
},
addText: function(str){
var elem = this.element;
if(elem.nodeName === 'text'){
elem.appendChild(doc.createTextNode(str+''));
}
return this;
},
setOpacity : function(v){
this.attr('fill-opacity',v);
return this;
},
setSize : function(v){
this[0].nodeName==='circle'
? this.attr('r',4+(v===0?0:2))
: this.attr({'stroke-width':v});
return this;
},
toFront: function() {
this[0].parentNode.appendChild(this[0]);
return this;
},
show:function(){
this[0].style.display = 'block';
return this;
},
hide:function(){
this[0].style.display = 'none';
return this;
},
destroy : function(){
//Destroy nodes............
var node = this[0] || this;
node.onmouseover = node.onmouseout = node.onclick = null;
node.parentNode
&&node.parentNode.removeChild(node);
return this;
}
};
//---------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
//If it is vml to modify some of these methods
if(!hasSVG){
//-----------------------------------------------------------------------------------------------------------------------------
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){
var name = nodeName || 'shape';
this.element= this[0] = (name === 'div' || name === 'span')
? doc.createElement(name)
: doc.createElement('<vml:'+name+'>');
this.graphic = graphic;
return this;
},
/*on : function(eventName, handler){
var self = this;
this.element.attachEvent("on" + eventName,function(){
handler.call(self);
});
return this;
},*/
addText : function(txt){
this[0].innerHTML = txt || '';
return this;
},
setSize : function(v){
this[0].strokeWeight = v;
return this;
},
setOpacity : function(v){
this.opacity.opacity=v;
return this;
}
});
}
//---------------------------------------------------------------------------------------------------
//Drawing category
//------------------------------------------------------------
win.smipleChart = function(){
this.init.apply(this,arguments);
};
smileChart.list = [];
smileChart.timer = null;
smileChart.lazyLoad = function(id){
id = id || '0'
smileChart.list[id]
&&smipleChart.list[id].loadMe();
};
smileChart.prototype = {
options: {
charts : {
paddingRight : 20,
radius : 200,
style: {
fontFamily : '"Lucida Grande", "Lucida Sans Unicode", 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)
var self = this;
this.width = container.offsetWidth;
this.height = container.offsetHeight;
this.currList = {};
this.uuuid = ++uuuid;
this.timer = null;
//The main collection form of drawing group
//{id: {dom:xx,show:true}}
this.mainGroup = {};
//What should be used when segmenting is to know which ones are hidden because it involves redrawing
this.hideList = {};
//The drawing in svg must have an svg tag vml and use div
this.container = hasSVG
? new vector().$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)
: new vector().$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';
var c = extend(true,{},this.options),
opts = this.opts = extend(true,c,options),
style = extend(opts.charts.style,{
width : this.width,
height : this.height
});
smileChart.list[this.uuuid] = this;
smileChart.timer = setTimeout(function(){
smileChart.lazyLoad();
},200);
},
loadMe : function(){
var opts = this.opts,
self = this,
type = opts.charts.type;
this.container = this.container
.on('mouseout',function(e){
var elem = 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];
//Some parameters required when calculating the drawing plate
this.getDrawArea()
.createTooltip() //Create a box for prompt information
.drawTitle() //Draw the title
//Draw the plate
'line,area,pie'.indexOf(type)>=0
&&(opts.charts.panel = 'x');
' pie,pies'.indexOf(type)<0
&&this.drawPanel();
this.drawLegend(opts.legend.type); //Draw color block bars
var type = {
line : 'drawLine',
area : 'drawArea',
columns : 'drawColumns',
pie : 'drawPie',
pies : 'drawPies',
segment : 'drawSegment'
}[opts.charts.type];
//Start drawing.........
this[type]();
//Delete node
this.loading.parentNode.removeChild(this.loading);
//Disconnect the reference
this.loading = null;
this.container.style.display = '';
setTimeout(function(){
smileChart.lazyLoad((++self.uuuid)+'');
},10)
},
createElement : function(nodeName){
return new vector().$c(this,nodeName);
},
group: function(name){
return this.createElement(hasSVG?'g':'div').attr('mark',name);
},
getDrawArea : function(){
var opts = this.opts,
width = this.width,
height = this.height,
title = opts.title,
subTitle = opts.subTitle,
area = {
// Remove the scale text width on the left side of the coordinate axis (estimated) 80 is the fixed value and only 80 is left to the left side of the fixed value.
areaWidth: width - 80,
// Remove the height of the text and markings under the axis
areaHeight : height - 40,
//The X position of the origin will be calculated below
startX : 0,
//The Y position of the origin will be calculated below
startY : 0,
// When drawing a pie chart with the x coordinate of the center, you need to know the position of the center of the circle.
centerX: 0,
// When drawing a pie chart with the y coordinate in the center, you need to know the position of the center of the circle.
centerY: 0
};
//If the main title exists, subtract the height of the main title otherwise subtract the height of 10
area.areaHeight -=(title.text !== '')
? title.y
: 10;
// Remove the subtitle height
area.areaHeight -=(subTitle.text !== '')
? subTitle.y
: 10
area.startX = 80;
area.startY = height - 40;
//The position of the center of the circle
area.centerX = width / 2;
area.centerY = height / 2;
//Leave some space on the right
area.areaWidth -=20;
//Leave some spacing on top
area.areaHeight -=15;
opts.area = area;
return this;
},
drawTitle : function(){
var opts = this.opts,
self = this,
arr = [opts.title,opts.subTitle,opts.yUnit],
//Basic parameters of the position of 3 title coordinates
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){
var text = title.text;
if(text){
var elem = 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);
//If it is 2, it means that the subtitle is used to put it vertically
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)')
}
}
});
return this;
},
//Drawing plates is more troublesome
drawPanel : function(type){
varopts = this.opts,
self = this,
area = opts.area,
chartsType = opts.charts.type,
isSegment = chartsType === 'segment',
//Is the type of plate horizontal or vertical plate
type = opts.charts.panel || 'x';
// Bottom plate
var drawAreaWidth = area.areaWidth,
drawAreaHeight = area.areaHeight,
//The coordinates of the origin
startX = area.startX,
startY = area.startY;
var allData = [],
minValue = 0,
maxValue = 10,
//The number of lines can only be between 1 and 10
lineNum = mathMin(10,mathMax(opts.yUnit.lineNum,1)),
staff;
//Combining all data
each(opts.chartData,function(i,o){
// If it is a bar chart, it is summed up for all data
isSegment
? each(o.data,function(j,d){
allData[j]
? allData[j] = allData[j] + (~~d)
: allData[j] = ~~d;
})
: allData = allData.concat(o.data)
});
//Sort all data to find the maximum value and minimum value below
allData.sort(function(a,b){return ab});
//Finish the maximum value and minimum value
maxValue = allData[allData.length - 1];
each(allData,function(i,o){
if(o!==null){
minValue = o;
return false;
}
});
//Main plate container
var panel = this.group('panel').appendTo();
var result = xx(minValue,maxValue,lineNum),
min = result.min,
max = result.max,
f = result.stf;
isSegment
&&(min = 0);
// means that the horizontal coordinate or double coordinate is drawn
if(type.toLowerCase()==='x'){
//Underground unit interval
varxPices = drawAreaWidth / opts.xUnit.units.length,
//The center point of unit interval
offset = xPices / 2,
yPices = drawAreaHeight / lineNum;
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
var y = 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);
var span = 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{
//Underground unit interval
varyPices = drawAreaHeight / (opts.xUnit.units.length),
//The center point of unit interval
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)
});
var xPices = drawAreaWidth / lineNum;
for(var i=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);
}
}
//-----------------------------------------------------------------------------------------------------
//Because the starting point is likely not started from 0, so the value of the part 0 must be added at the starting point.
var jianju =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 axis starting point
startY : startY , // Y axis starting point
xPices : xPices, // Width of each portion of the X axis
yPices : yPices, // The width of each portion of the Y axis
offset: offset, // X Single branch center point position offset
jianjuY : jianju*yPices/f,
jianjuX : jianju*xPices/f,
feed : f // How many per Y axis are there
}
return this;
},
createTooltip: function(){
//A group
this.tipC = this.group('tip')
.css({zIndex: 200,height:'20px',width:'20px',position:'absolute'})
.appendTo()
.hide()
//Draw a frame baseDraw
this.tipBox = this.baseDraw.rect(this,{arc:0.22,fill:'#ffff',border:2,borderColor:'#606060'})
.appendTo(this.tipC)
//Because g in svg can be directly positioned, but the group rendering in vml is very slow, so the div is changed, so the parent here is not the same as the foreign
var p = 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);
return this;
},
showTooltip : function(obj, x, y, data){
/*var txt = 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);
var txt = 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{
var move = function(t,b,c,d){
return c*(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++;
var x = 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){
var self = this,
opts = this.opts,
isLine = opts.charts.type === 'line',
//The size of the color block
t_width = 20,
t_height = 20,
//Distance between blocks
t_space = 5,
datas = opts.chartData,
len = datas.length,
css = opts.legend.style,
// If the maximum length is longitudinal, the maximum length is required
maxWidth = 10,
maxHeight= 30,
//The location of this thing
orig_pos = opts.legend.pos?opts.legend.pos:[2,2],
//Show hidden group functions
handle = function(i){
var g = 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 it is a segmented picture, it will involve redrawing.
if(issegment){
self.hideList[i] ='';
var mainGroup = self.mainGroup;
for(var name in mainGroup){
var parent = mainGroup[name].chart,
nodes = parent[0].childNodes,
len = nodes.length;
//Destroy the things drawn on the picture
for(var i = len-1;i>=0;i--){
vector.prototype.destroy.call(nodes[i])
}
}
//Repaint
self.drawSegment();
}
}else{
g.chart.show();
g.show = true;
hasSVG
? this.attr({fill:'#000'})
: this[0].style.color = '#000'
if(issegment){
delete self.hideList[i];
var mainGroup = self.mainGroup;
for(var name in mainGroup){
var parent = mainGroup[name].chart,
nodes = parent[0].childNodes,
len = nodes.length;
for(var i = len-1;i>=0;i--){
vector.prototype.destroy.call(nodes[i])
}
}
self.drawSegment();
}
}
},
arr = [];
type = type ||'lateral';
var legendPanel = self.group('Legend')
.appendTo();
if(type==='lateral'){
//If it's horizontal
var top = 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;
//Calculate the location of all left
//If it is a linear diagram, draw the drawing in the form of a linear diagram
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;
var w = 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{
var top = 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);
var h = 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 it is a multi-layer pie chart, it cannot be hidden
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);
}
return this;
},
drawLine : function(){
var self = this,
opts = this.opts,
draw = opts.draw;
each(opts.chartData,function(i,o){
var id = 'chart'+i,
lineGroup = self.group(id)
.appendTo();
self.mainGroup[id]={
chart : lineGroup,
show : true
};
var path = [M],
data = o.data,
line;
for(var i = 0,l = data.length; i < l ; i++){
if( data[i] == null){
//If this data does not exist and is not the first data path, add M to it
if(path[path.length - 1] !== M)
path.push(M);
}else{
//If it is not the first data path, add L
i !== 0 && path.push("L");
//If the first one is null and not the first one to remove the L
if(i > 0 && data[i - 1] == null)
path.pop();
// Calculate the position of x and y of the point
var x = 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);
//Draw points
var dotType = o.dotType||'circle';
self.baseDraw[dotType](self,{
x : x,
y : y,
r: 4,
fillColor : o.color
})
.attr({data:data[i],pos:x+'-'+(y-5)})
.css({zIndex:10,cursor:'pointer'})
.on('mouseover',(function(o,x,y){
return function(){
if(self.currList.dot){
if(self.currList.dot[0] === this[0])
return;
self.currList.dot.setSize(0);
self.currList.line.setSize(1.5);
}
this.setSize(2);
line.setSize(2.5);
var pos = this.attr('pos').split('-');
self.showTooltip(o,pos[0],pos[1],this.attr('data'));
self.currList.dot = this;
self.currList.line = line;
}
})(o,x,y))
/*.on('mouseout',function(){
this.setSize(0);
line.setSize(1.5);
})*/
.on('click',function(){lineGroup.toFront(); })
.appendTo(lineGroup);
}
};
//Draw folded lines
line = self.baseDraw.path(self,{
border: 1.5,
borderColor: o.color,
isfill : false,
path : path
})
.css({zIndex:5})
/*.on('mouseover',function(){
this.setSize(2.5);
})
.on('mouseout',function(){
this.setSize(1.5);
})*/
.on('click',function(){lineGroup.toFront();})
.appendTo(lineGroup);
});
return this;
},
drawArea : function(){
var self = this,
opts = this.opts,
draw = opts.draw;
each(opts.chartData,function(i,o){
var id = 'chart' + i,
areaGroup = self.group(id).appendTo();
self.mainGroup[id] = {chart : areaGroup,show : true};
//There are 2 paths, one is the path of the region and the other is the path of the line
var areaPath = [M, (draw.startX + draw.offset).toFixed(0), (draw.startY-draw.jianjuY).toFixed(0)],
path = [M],
data = o.data,
line;
for(var n=0,l = data.length;n<l;n++){
//If the data is empty
var len = areaPath.length;
if( data[n] === null){
//If the previous one is not m, then draw it again so add M
if(path[path.length - 1] !== M)
path.push(M);
//If the first or the front are null, modify the starting point coordinates
len===3
&&(areaPath[1] = (draw.startX +(n+1)*draw.xPices + draw.offset).toFixed(0));
//If the previous one is not the end identifier area graph, if the first data is null, the following operation will not be performed
if(areaPath[len - 1] !== seal&&n!==0){
areaPath=areaPath.concat([
areaPath[len - 2],
(draw.startY-draw.jianjuY).toFixed(0),
seal
]);
}
}else{
n !== 0 && path.push(L);
areaPath.push(L);
//If the previous data is null, remove the previous L
if(n > 0 && data[n - 1] == null){
path.pop();
//If the first one is null, do not delete L
n!==1&&areaPath.pop();
}
var x = draw.startX + draw.offset + (n * draw.xPices),
y = draw.startY - data[n] * (draw.yPices / draw.feed);
if(isIE){
x = parseInt(x);
y = parseInt(y);
}
path.push(x);
path.push(y);
if(areaPath[len - 1] === seal){
areaPath = areaPath.concat([
M,
x,
parseInt(draw.startY-draw.jianjuY),
L,
x,
y
]);
}else{
areaPath.push(x);
areaPath.push(y);
}
//If it is the last point
if(n === l - 1){
areaPath.push(x);
areaPath.push(parseInt(draw.startY-draw.jianjuY));
}
//Draw points
self.baseDraw[o.dotType || 'circle'](self,{
x : x,
y : y,
r: 4,
fillColor : o.color
})
.attr({data:data[n],pos:x+'-'+(y-5)})
.on('mouseover',(function(o,x,y){
return function(){
if(self.currList.dot){
if(self.currList.dot[0] === this[0])
return;
self.currList.dot.setSize(0);
self.currList.line.setSize(1.5);
}
this.setSize(2);
line.setSize(2.5);
var pos = this.attr('pos').split('-');
self.showTooltip(o,pos[0],pos[1],this.attr('data'));
self.currList.dot = this;
self.currList.line = line;
}
})(o,x,y))
/*.on('mouseout',function(){
this.setSize(0);
line.setSize(1.5);
//self.hideTooltip()
})*/
.on('click',function(){areaGroup.toFront(); })
.css({zIndex:10,cursor:'pointer'})
.appendTo(areaGroup);
}
}
areaPath.push(seal)
self.baseDraw.path(self,{
border : 0,
isfill : true,
fillColor : o.color,
opacity: 0.5,
path : areaPath
})
.css({zIndex:5})
.appendTo(areaGroup);
line = self.baseDraw.path(self,{
border: 1.5,
borderColor: o.color,
isfill : false,
path : path
})
/*.on('mouseover',function(){
hasSVG
? this.attr({'stroke-width':2.5})
: (this[0].strokeWeight = 2.5);
})
.on('mouseout',function(){
hasSVG
? this.attr({'stroke-width':1.5})
: (this[0].strokeWeight = 1.5);
})*/
.on('click',function(){areaGroup.toFront(); })
.css({zIndex:-1})
.appendTo(areaGroup);
});
return this;
},
drawColumns: function(){
var self = this,
opts = this.opts,
draw = opts.draw,
chartData = opts.chartData,
dataLen = chartData.length,
//The spacing between multiple columns
columnSpace = 3,
//Sum of all intervals in a position
columnPadding = columnSpace * dataLen + columnSpace,
//The width of each column
columnSize = self.opts.charts.panel==='x'
? Number(((draw.xPices - columnPadding) / dataLen).toFixed(0))
: Number((((draw.yPices - columnPadding) / dataLen).toFixed(0));
each(chartData, function(i,o){
var data = o.data,
id = 'chart' + i,
isX = opts.charts.panel==='x',
colGroup = self.group(id).appendTo(),
//The starting position of each point
start = self.opts.charts.panel==='x'
? draw.startX + columnSpace + i*(columnSize+columnSpace)
: draw.startY + columnSpace + i*(columnSize+columnSpace)
self.mainGroup[id] = {chart:colGroup,show:true};
for(var j = 0,l=data.length; j < l ; j++){
if(data[j]===null) continue;
//If it's a sideways plate
if(isX){
var x = Number((start + j *draw.xPices ).toFixed(0)),
y = Number((draw.startY-draw.jianjuY).toFixed(0)),
height = Number((data[j] * (draw.yPices / draw.feed)-draw.jianjuY).toFixed(0)),
path = [
M,
x,
y,
L,
x,
y -height,
L,
x + columnSize,
y - height,
L,
x + columnSize,
y,
seal
];
var pos = [x+columnSize/2,data[j]>0?y-height:draw.startY-draw.jianjuY];
}else{
var x = Number((draw.startX+draw.jianjuX).toFixed(0)),
width = Number((data[j]*((draw.xPices / draw.feed))-draw.jianjuX).toFixed(0)),
y = Number((start - (j+1) *draw.yPices ).toFixed(0)),
path = [
M,
x,
y,
L,
x+width,
y ,
L,
x + width,
y + columnSize,
L,
x,
y+ columnSize,
seal
];
var pos = [draw.startX+draw.jianjuX+width/2,y];
}
self.baseDraw.path(self,{
border : 0,
isfill : true,
fillColor : o.color,
opacity: 1,
path : path
})
.attr({data:data[j],pos:pos[0]+'-'+pos[1]})
.css({zIndex:5,cursor:'pointer'})
.on('mouseover',(function(d){
return function(){
this.setOpacity(0.85);
var pos= this.attr('pos').split('-')
self.showTooltip(o,pos[0],pos[1],this.attr('data'));
}
})(data[j])
)
.on('mouseout',function(){
this.setOpacity(1);
})
.appendTo(colGroup);
}
});
return this;
},
drawPie : function(){
var self = this,
opts = this.opts,
area = opts.area,
rx = area.centerX,
ry = area.centerY,
inc = 0,
total = 0,
data = [],
cumulative = -0.25, // start at top;
circ = 2 * Math.PI,
radiu = mathMin(opts.charts.radius,mathMin(area.areaWidth/2,area.areaHeight/2)),
fraction,
half_fraction;
each(opts.chartData,function(i,o){
typeof o.data ==='object'
? (data.push((function(o){
var all =0;
for(var i in o)
all+=~~o[i]
Return all
})(o.data)))
:data.push(mathAbs(o.data))
});
each(data,function(i,o){
total = total + o;
});
each(data,function(i,o){
var pieGroup = self.group('chart'+i).appendTo(),
s = inc/total*360,
e = (inc + o)/total*360,
name = opts.chartData[i].name,
size = calTextLen(name),
dot = angle(radiu,[rx,ry],s+(es)/2,2),
x = rx + (dot[0]-rx)/2 - size.w/2,
y = ry + (dot[1]-ry)/2 - size.h/2,
len = Math.sqrt((x-rx)*(x-rx)+(y-ry)*(y-ry)),
moveDisplacement = ((x-rx)*8/len)+','+((y-ry)*8/len);
inc = inc + o;
var value = Number(o);
fraction = total ? value / total : 0;
half_fraction = total ? (value / 2) / total : 0;
var start = cumulative * circ;
half_cumulative = cumulative + half_fraction;
cumulative += fraction;
var end = cumulative * circ;
self.baseDraw.pie(self,{
config : opts.chartData[i],
s : start,
e : end,
r : radiu,
innerR: 0
})
.css({zIndex:5,cursor:'pointer'})
.attr({move:moveDisplacement,pos:dot[0]+'-'+dot[1]})
.on('mouseover',function(){
this.setOpacity(0.85);
var pos = this.attr('pos').split('-');
self.showTooltip(opts.chartData[i],pos[0],pos[1],((es)/360*100).toFixed(0)+'%')
})
.on('mouseout',function(e){
var elem = e.toElement || e.relatedTarget;
//If you encounter the text inside or the prompt box will not disappear
if(!elem||contains(this[0].parentNode,elem)||contains(self.tipC[0],elem))
return;
self.hideTooltip();
this.setOpacity(1);
})
.on('click',function(){
var m = this.attr('move')
if(m.indexOf('+')>0){
hasSVG
? this.attr({
transform: 'translate(0,0)'
})
: this.css({
left : '0px',
top : '0px'
})
this.attr({move:m.replace('+','')});
}else{
var s= m.split(',');
hasSVG
? this.attr({
transform: 'translate('+m+')'
})
: this.css({
left : s[0]+'px',
top : s[1]+'px'
})
this.attr({move:m+'+'});
}
})
.appendTo(pieGroup);
self.mainGroup['chart'+i] = {
chart : pieGroup,
show : true
};
self.baseDraw.span(self,{
x : x,
y : y,
fill : '#fff',
'text-anchor':'left'
})
.css({
fontFamily : 'Verdana,Arial,Helvetica,sans-serif',
fontSize : '12px',
position : 'absolute',
color : '#fff',
cursor : 'pointer',
zIndex : 10
})
.addText(name)
.appendTo(pieGroup);
});
},
drawPies : function(){
var self = this,
opts = this.opts,
area = opts.area,
rx = area.centerX,
ry = area.centerY,
total = 0,
data = [],
chartData = opts.chartData,
cumulative = -0.25, // start at top;
circ = 2 * Math.PI,
radiu = mathMin(opts.charts.radius,mathMin(area.areaWidth/2,area.areaHeight/2)),
fraction,
half_cumulative,
half_fraction;
each(chartData,function(i,o){
each(o.data,function(j,d){
data[j]
? data[j] +=mathAbs(d)
: data[j] =mathAbs(d)
});
});
//看有多少个数据来生成来生成内半径
var len = data.length,
innerSpace = radiu / 10;
Rpice = (radiu - innerSpace) / len;
each(data,function(i,d){
var inc = 0;
if(d===0) return;
each(chartData,function(j,o){
if(~~o.data[i]===0)return;
var outR = radiu - Rpice * i,
innerR = radiu - Rpice * (i + 1),
value = ~~o.data[i],
fraction = value / d;
half_fraction = (value/2)/d ,
start = cumulative * circ,
s = inc/d*360,
e = (inc + value)/d*360,
id = 'chart'+j,
piesGroup = self.mainGroup[id]?self.mainGroup[id].chart:self.group(id).appendTo();
!self.mainGroup[id]
&&(self.mainGroup[id] = {chart:piesGroup,show:true});
inc = inc + value;
varname = o.name,
size = calTextLen(name),
dot = angle(radiu,[rx,ry],s+(es)/2,2),
showDot = angle(radiu- Rpice * i,[rx,ry],s+(es)/2,2),
px = dot[0]>rx?1:-1,
py = dot[1]>ry?1:-1;
var x = rx + px*innerSpace + ((dot[0]-rx-px*innerSpace)/len)*(len-i-1)+((dot[0]-rx-px*innerSpace)/len)/2- size.w/2,
y = ry + py*innerSpace +((dot[1]-ry-py*innerSpace)/len)*(len-i-1)+((dot[1]-ry-py*innerSpace)/len)/2- size.h/2;
half_cumulative = cumulative + half_fraction,
cumulative += fraction,
end = cumulative * circ;
self.baseDraw.pie(self,{
config : o,
s : start,
e : end,
r : outR,
innerR : innerR
})
.attr({m : i+'-'+j,data:((es)/360*100).toFixed(0)+'%',pos:showDot[0]+'-'+showDot[1]})
.css({zIndex:5,cursor:'pointer'})
.on('mouseover',function(){
this.setOpacity(0.85);
var pos = this.attr('pos').split('-');
self.showTooltip(o,pos[0],pos[1],this.attr('data'))
})
.on('mouseout',function(e){
var elem = e.toElement || e.relatedTarget;
if(!elem||elem.getAttribute('m')===this[0].getAttribute('m'))
return;
this.setOpacity(1);
})
.appendTo(piesGroup);
self.baseDraw.span(self,{
x : x,
y : y,
fill : '#fff',
'text-anchor':'left'
})
.attr({m : i+'-'+j})
.css({
fontFamily : 'Verdana,Arial,Helvetica,sans-serif',
fontSize : '12px',
position : 'absolute',
color : '#fff',
cursor : 'pointer',
zIndex : 10
})
.addText(name)
.appendTo(piesGroup);
});
});
},
drawSegment : function(){
var self = this,
opts = this.opts,
draw = opts.draw,
chartData = opts.chartData,
typeIsX = opts.charts.panel==='x',
columnPad = 5,
prev = [],
columnSize = ~~(typeIsX?draw.xPices:draw.yPices) - columnPad * 2;
each(chartData,function(i,c){
if(i in self.hideList)
return;
var id = 'chart' + i,
segmentGroup = self.mainGroup[id]?self.mainGroup[id].chart:self.group(id).appendTo();
self.mainGroup[id] = {chart : segmentGroup,show : true};
each(c.data,function(j,d){
if(d===null||d===0)
return;
if(typeIsX){
var start = draw.startX + columnPad,
x = ~~(start + j*draw.xPices).toFixed(0),
y = ~~(draw.startY-(prev[j]?prev[j]:0)).toFixed(0),
size = ~~(d*draw.yPices / draw.feed ).toFixed(0),
path = [
M,
x,
y,
L,
x,
y - size,
L,
x + columnSize,
y - size,
L,
x + columnSize,
y,
seal
];
var pos = [x + columnSize/2,y-size];
}else{
var start = draw.startY - columnPad,
x = ~~(draw.startX+(prev[j]?prev[j]:0)).toFixed(0) ,
y = ~~(start- j*draw.yPices).toFixed(0),
size = ~~(d*draw.xPices / draw.feed ).toFixed(0),
path = [
M,
x,
y,
L,
x + size,
y ,
L,
x + size,
y - columnSize,
L,
x ,
y - columnSize,
seal
];
var pos = [x+size/2,y - columnSize];
}
self.baseDraw.path(self,{
border : 0,
isfill : true,
fillColor : c.color,
opacity : 1,
path : path
})
.attr({data:d,pos:pos[0]+'-'+pos[1]})
.on('mouseover',function(){
this.setOpacity(0.85);
var pos = this.attr('pos').split('-');
self.showTooltip(chartData[i],pos[0],pos[1],this.attr('data'))
})
.on('mouseout',function(){
this.setOpacity(1);
})
.css({zIndex:5,cursor:'pointer',left:'0px',top:'0px'})
.appendTo(segmentGroup);
prev[j]
? prev[j] = prev[j] + size
: prev[j] = size;
});
});
},
baseDraw : {
rect : function(o,config){
return o.createElement('rect')
.attr({
rx : config.arc*30 || 5,
ry : config.arc*30 || 5,
width : config.width || 50,
height : config.height || 50,
fill : config.fill || '#fff',
'fill-opacity' : config.opacity || 0.85,
'stroke-width' : config.border || 2,
stroke : config.borderColor || '#606060',
transform : 'translate('+(config.left||0)+','+(config.top||0)+')'
});
},
text : function(o,config){
return o.createElement('text')
.attr(config);
},
span : function(o,config,v){
return o.createElement('text')
.attr(config)
.attr({
y : config.y+(v||15)
});
},
path : function(o,config){
var set = {};
set['stroke-width'] = config.border;
set.stroke = config.borderColor || '#C0C0C0';
set.fill = config.isfill?config.fillColor:'none';
set.d = config.path;
config.opacity
&&(set['fill-opacity'] = config.opacity);
return o.createElement('path')
.attr(set);
},
circle : function(o,config){
var set = {};
set.cx = config.x;
set.cy = config.y;
set['stroke-width'] = 0;
set.stroke = config.borderColor || '#C0C0C0';
set.r = config.r;
set.fill = config.fillColor;
return o.createElement('circle')
.attr(set);
},
square : function(o,config){
var x = config.x,
y = config.y,
r = config.r,
color= config.fillColor,
len = r,
path = [
M,
(x-len).toFixed(0),
(y-len).toFixed(0),
L,
(x+len).toFixed(0),
(y-len).toFixed(0),
(x+len).toFixed(0),
(y+len).toFixed(0),
(x-len).toFixed(0),
(y+len).toFixed(0),
seal
];
return o.baseDraw.path(o,{
border : 1,
borderColor : color,
isfill : true,
fillColor : color,
path : path
});
},
triangle : function(o,config){
var x = config.x,
y = config.y,
r = config.r+0.1,
color = config.fillColor,
path = [
M,
x.toFixed(0),
(y-1.33*r).toFixed(0),
L,
(x+r).toFixed(0),
(y+0.67*r).toFixed(0),
(xr).toFixed(0),
(y+0.67*r).toFixed(0),
seal
];
return o.baseDraw.path(o,{
border : 1,
borderColor : color,
isfill : true,
fillColor : color,
path : path
});
},
diamond : function(o,config){
var x = config.x,
y = config.y,
r = 1.35*config.r,
color = config.fillColor,
path = [
M,
x.toFixed(0),
(yr).toFixed(0),
L,
(x+r).toFixed(0),
y.toFixed(0),
x.toFixed(0),
(y+r).toFixed(0),
(xr).toFixed(0),
y.toFixed(0),
seal
];
return o.baseDraw.path(o,{
border : 1,
borderColor : color,
isfill : true,
fillColor : color,
path : path
});
},
pie : function(o,config){
//config,s,e,r,index
var opts = o.opts,
s = config.s,
r = config.r,
e = config.e - 0.000001,
id = 'chart'+config.index,
area = opts.area,
rx = area.centerX,
ry = area.centerY,
cosStart = mathCos(s),
sinStart = mathSin(s),
cosEnd = mathCos(e),
sinEnd = mathSin(e),
color = config.config.color,
innerR = config.innerR,
longArc = e - s < Math.PI ? 0 : 1,
path = [
M,
rx + r * cosStart,
ry + r * sinStart,
'A',
r,
r,
0,
longArc,
1,
rx + r * cosEnd,
ry + r * sinEnd,
L,
rx + innerR * cosEnd,
ry + innerR * sinEnd,
'A', // arcTo
innerR, // x radius
innerR, // y radius
0, // slanting
longArc, // long or short arc
0, // clockwise
rx + innerR * cosStart,
ry + innerR * sinStart,
'Z'
];
return o.baseDraw.path(o,{
border : 1,
border : '#fff',
isfill : true,
fillColor : color,
opacity : 1,
path : path
})
}
}
};
//---------------------------------------------------------------------------------------------------
//如果是vml 修改smipleChart.prototype中的一些方法
!hasSVG
&&extend(smipleChart.prototype.baseDraw,{
rect : function(o,config){
var attr = {},
css = {};
attr.arcsize = config.arc || 0.2 +'';
if(config.fill==='none'){
attr.filled = 'f'
}else{
attr.filled = 't';
attr.fillcolor = config.fill || '#fff';
}
attr.strokeWeight = config.border || 2;
attr.strokeColor = config.borderColor || '#606060';
css.width = config.width || 50 +'px';
css.height = config.height || 50 +'px';
css.zIndex = 10;
css.left = config.left||0+'px';
css.top = config.top ||0+'px';
return o.createElement('roundrect')
.attr(attr)
.css(css);
},
text : function(o,config){
return o.createElement('TextBox')
.attr({inset : "2px,2px,2px,2px" })
.css({zIndex:200})
},
span : function(o,config){
return o.createElement('span').
css({
position:'absolute',
left : config.x+'px',
top : config.y+'px'
})
},
path : function(o,config){
var attr = {},
width = o.width,
height = o.height,
css = {
width : width+'px',
height : height+'px'
};
if(config.border===0){
attr.Stroked = 'f';
attr.strokeWeight =0;
}else{
attr.strokeWeight = config.border||1 ;
}
attr.strokeColor = config.borderColor || "#C0C0C0";
attr.filled = config.isfill?'t':'f';
attr.filled==='t'
&&(attr.fillcolor=config.fillColor||"#C0C0C0");
attr.coordsize = width+','+height;
attr.path = config.path;
var elem = o.createElement()
.attr(attr)
.css(css);
if(config.opacity){
var fill = o.createElement('fill')
.attr({
type : 'fill',
color : config.fillColor||"#C0C0C0",
opacity : config.opacity
})
.appendTo(elem);
//那这个对象的一个属性引用设置透明的元素以后会用到
elem.opacity = fill[0];
}
return elem;
},
circle : function(o,config){
var width = o.width,
height = o.height,
attr = {
strokeWeight : 1,
coordsize : width+','+height,
filled : 't'
},
css ={
width : width+'px',
height : height+'px'
}
x = config.x,
y = config.y,
r = config.r;
attr.strokeColor=attr.fillcolor = config.fillColor
attr.path =[
'wa', // clockwisearcto
x - r, // left
y - r, // top
x + r, // right
y + r, // bottom
x + r, // start x
y, // start y
x + r, // end x
y, // end y
'e' // close
];
return o.createElement()
.attr(attr)
.css(css)
},
pie : function(o,config){
////config,s,e,r,index
var opts = o.opts,
area = opts.area,
r = config.r,
rx = area.centerX,
ry = area.centerY,
innerR= config.innerR||0,
sDot = angle(r,[rx,ry],s,2),
eDot = angle(r,[rx,ry],e,2),
color = config.config.color,
s = config.s,
e = config.e,
e = e - s == 2 * Math.PI ? e - 0.001 : e,
cosStart = mathCos(s),
sinStart = mathSin(s),
cosEnd = mathCos(e),
sinEnd = mathSin(e),
path = [
'wa', // clockwisearcto
(rx - r).toFixed(0), // left
(ry - r).toFixed(0), // top
(rx + r).toFixed(0), // right
(ry + r).toFixed(0), // bottom
(rx + r * cosStart).toFixed(0), // start x
(ry + r * sinStart).toFixed(0), // start y
(rx + r * cosEnd).toFixed(0), // end x
(ry + r * sinEnd).toFixed(0), // end y
'at', // clockwisearcto
(rx - innerR).toFixed(0), // left
(ry - innerR).toFixed(0), // top
(rx + innerR).toFixed(0), // right
(ry + innerR).toFixed(0), // bottom
(rx + innerR * cosEnd).toFixed(0), // start x
(ry + innerR * sinEnd).toFixed(0), // start y
(rx + innerR * cosStart).toFixed(0), // end x
(ry + innerR * sinStart).toFixed(0), // end y
'x', // finish path
'e' // close
];
return o.baseDraw.path(o,{
border : 1,
border : '#fff',
isfill : true,
fillColor : color,
opacity : 1,
path : path
})
}
});
//---------------------------------------------------------------------------------------------------
})(document);
window.onload = function(){
var t = new Date().getTime();
var config = {
charts : {
type : 'line',
radius : 150,
panel : 'x',
style: {
fontFamily: '"Lucida Grande", "Lucida Sans Unicode", Verdana, Arial, Helvetica, sans-serif', // default font
fontSize: '12px'
}
},
title : {
text: '线性图表',
y: 10,
style: {
color: 'black',
fontSize: '16px'
}
},
subTitle : {
text: '线性图表副标题',
y: 35,
style: {
color: '#111',
fontSize: '12px'
}
},
legend : {
enable : true,
//type : 'lateral', // lateral 横向或lengthwise 纵向
type : 'lateral',
pos : [10,10],
style:{
fontFamily : '"Lucida Grande", "Lucida Sans Unicode", Verdana, Arial, Helvetica, sans-serif', // default font
fontSize : '12px',
magin : '0px'
}
},
yUnit : {
text : '线性图表侧标题',
x : 20,
style : {
color : '#111',
fontSize : '12px'
}
},
xUnit : {
units: [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'
]
},
chartData : [
{
name : 'xcv',
color : '#4572A7',
dotType : 'square',
//data : [11,12,13,15,16,18,17,14,10]
//[1,2,3,5,6,8,7,4,10]
data: [44,-12,-78,100,-13,-4,-26,34]
}, {
name: 'frfr',
color: '#AA4643',
dotType : 'triangle',
data: [-44,12,78,-100,13,4,-56,-34]
}, {
name: 'AAAAA',
color: '#89A54E',
dotType : 'diamond',
data: [null,78,83,null,22,-78,2,44,78]
}, {
name: 'BBBB',
color: '#80699B',
data: [null, 58, 35, null, 52, 47, 26, -55, 39, 123,15,66]
}
]
};
new smipleChart($$('line'),config);
config.charts.type ='area';
config.title.text ='区域图表'
config.subTitle.text='区域图表副标题'
config.yUnit.text ='区域图表侧标题'
config.chartData = [
{
name : 'xcv',
color : '#4572A7',
//data : [0,3,4,5,6,7,8,9,10,11]
data : [11,12,13,14,15,16,-17,18,19,0]
}, {
name: 'frfr',
color: '#AA4643',
data: [44,12,78,100,13,44,56,34]
}, {
name: 'AAAAA',
color: '#89A54E',
data: [null,101,83,null,22,78,88,44,78]
}, {
name: 'BBBB',
color: '#80699B',
data: [null, 58, 35, null, 52, 47, 26, 55, 39, 123,15,66]
}
]
new smipleChart($$('area'),config);
config.title.text ='柱状图表'
config.subTitle.text='柱状图表副标题'
config.yUnit.text ='柱状图表侧标题'
config.charts.type ='columns';
config.chartData =[
{
name : 'xcv',
color : '#4572A7',
//data : [2,3,4,5,6,7,8,9,10,11]
data : [-0.01,-0.62,0,0.55,null,0.78,-0.63,-0.82,null,null,0.33]
}, {
name: 'frfr',
color: '#AA4643',
data: [-0.22,0.82,0.55,1.32,0.33,0.95,null,1,0.65,null,0.78]
}, {
name: 'AAAAA',
color: '#89A54E',
data: [null,0.62,0.34,null,0.63,0,-0.23,-1,0.62,0.45,null,-0.56]
}
]
new smipleChart($$('zhu'),config);
config.charts.panel='y'
new smipleChart($$('zhu1'),config);
config.charts.type ='pie';
config.title.text ='饼图图表'
config.subTitle.text='饼图图表副标题'
config.yUnit.text =''
config.legend.type='lengthwise';
config.chartData =[
{
name : 'aaa',
color : '#4572A7',
data : [433,123,null,66]
}, {
name: 'bbb',
color: '#AA4643',
data: [45,33,33,411]
}, {
name: 'ccc',
color: '#89A54E',
data: [55,null,75,233]
}, {
name: 'ddd',
color: '#80699B',
data: [63,null,100,333]
}
]
config.legend.pos= [680,30]
new smipleChart($$('pie'),config);
config.charts.type ='pies';
config.title.text ='多层饼图图表'
config.subTitle.text='多层饼图图表副标题'
config.legend.type='lateral';
config.legend.pos= [290,400]
new smipleChart($$('pies'),config);
config.chartData =[
{
name : 'xcv',
color : '#4572A7',
data : [111,222,333,null,444,555,56,57,84]
}, {
name: 'frfr',
color: '#AA4643',
data: [845,666,100,null,666,677,56,88,633,55,555]
}, {
name: 'AAAAA',
color: '#89A54E',
data: [555,162,75,null,364,0,637,112,163,615]
}
]
config.charts.type ='line';
config.legend.pos= [10,10]
//
config.yUnit.lineNum = 10;
config.charts.panel = 'x';
config.title.text ='分段图表'
config.subTitle.text='分段图表副标题'
config.yUnit.text ='分段图表侧标题'
config.charts.type ='segment';
new smipleChart($$('segmentx'),config);
config.charts.panel = 'y';
new smipleChart($$('segmenty'),config);
config.yUnit.lineNum = 2;
config.title.text ='比较小的'
config.subTitle.text='只设置了2条线'
config.yUnit.text ='小测标题';
new smipleChart($$('vv'),config);
//alert(new Date().getTime()-t)
}
</script>
</body>
</html>
Other
js浮点精度问题不好解决求助。 . . . . . . . .
水平有限难免问题多多望赐教。 . . . . . .