支持 线性图 区域图 柱状图 饼图
支持多浏览器
用到的是svg vml
另
js浮点精度问题 不好解决 求助。。。。。。。。。
水平有限 难免问题多多 望赐教。。。。。。。
<!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' class="cc"></div> <div id='area' class="cc"></div> <div id='zhu' class="cc"></div> <div id='zhu1' class="cc" style="height:600px;"></div> <div id='segmentx' class="cc"></div> <div id='segmenty' class="cc"></div> <div id='pie' class="cc"></div> <div id='pies' class="cc"></div> <div id='vv' class="cc" 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*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; }); }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; }); } //上面找到间隔后 找到间隔中最接近的一个 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)%v-v)*t; a = (a*t+ba)/t; b = (b*t+(b%v===0?0:(v-b%v))*t)/t; //看看还剩几条线没有画 var num = 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}; } //--------------------------------------------------------------------------------------------------------------- //对svg vml元素的一些创建 修改属性 样式 删除 == 一些的操作 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(){ //销毁节点...................... var node = this[0] || this; node.onmouseover = node.onmouseout = node.onclick = null; node.parentNode &&node.parentNode.removeChild(node); return this; } }; //--------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------- //如果是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){ var name = nodeName || 'shape'; this.element= this[0] = (name === 'div' || name === 'span') ? doc.createElement(name) : doc.createElement('<vml:'+name+' class="vml">'); 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; } }); } //--------------------------------------------------------------------------------------------------- //画图类 //------------------------------------------------------------ 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 : '"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; //主要画图组的集合 形式 //{id : {dom:xx,show:true}} this.mainGroup = {}; //分段的时候要用到的 知道哪些是隐藏了的 因为要涉及到重绘 this.hideList = {}; //svg 里面画图 必须有一个svg标签 vml就用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 }); smipleChart.list[this.uuuid] = this; smipleChart.timer = setTimeout(function(){ smipleChart.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]; //计算绘画盘子的时候需要的一些参数 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); //画色块条 var type = { 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){ 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 = { // 去掉坐标轴左边的刻度文本宽度(预估) 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; return this; }, drawTitle : function(){ var opts = 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){ 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); //如果为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)') } } }); return this; }, //画盘子 比较麻烦 drawPanel : function(type){ var opts = this.opts, self = this, area = opts.area, chartsType = opts.charts.type, isSegment = chartsType === 'segment', //盘子的类型 是横盘子 还是纵盘子 type = opts.charts.panel || 'x'; // 底板 var drawAreaWidth = area.areaWidth, drawAreaHeight = area.areaHeight, //原点的坐标 startX = area.startX, startY = area.startY; var allData = [], 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){return a-b}); //求出最大值 最小值 maxValue = allData[allData.length - 1]; each(allData,function(i,o){ if(o!==null){ minValue = o; return false; } }); //主盘子容器 var panel = this.group('panel').appendTo(); var result = 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; //--------------------------------画横向的点和文字--------------------------------------------------------- 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{ //横坐标单位间隔 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) }); 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); } } //----------------------------------------------------------------------------------------------------- //因为起点很可能不是从0开始的 所以在起点的时候要要加上到0那部分的值 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 轴起点 startY : startY , // Y 轴起点 xPices : xPices, // X 轴每份的宽度 yPices : yPices, // Y 轴每份的宽度 offset : offset, // X 单分中心点位置偏移量 jianjuY : jianju*yPices/f, jianjuX : jianju*xPices/f, feed : f // Y 轴的每份有多少 } return this; }, 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 所以这里的父不一洋 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', //颜色块的大小 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){ 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(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; //销毁图上面画的东西 for(var i = 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){ 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'){ //如果是横着的 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; //计算所有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; 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(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){ //如果这个数据不存在 并且不是第一个数据 路径上加 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的位置 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); //画点 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); } }; //画折线 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}; //有2个路径 一个是区域的路径 一个是线的路径 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++){ //如果数据是空的 var len = areaPath.length; if( data[n] === null){ //如果前面的一个不是m 就重新画 所以加上 M if(path[path.length - 1] !== M) path.push(M); //如果第1个 或者前面的都为null 修改起点坐标 len===3 &&(areaPath[1] = (draw.startX +(n+1)*draw.xPices + draw.offset).toFixed(0)); //如果前面一个不是结束标识符 区域图结束 如果第一个数据是null 则不进行下面的操作 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); //如果前面的那个数据是null 把之前的那个L去掉 if(n > 0 && data[n - 1] == null){ path.pop(); //如果是第一个为null 不删除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(n === l - 1){ areaPath.push(x); areaPath.push(parseInt(draw.startY-draw.jianjuY)); } //画点 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, //多个柱子之间的间距 columnSpace = 3, //一个位置中 所有的间隔之和 columnPadding = columnSpace * dataLen + columnSpace, //每个柱子的宽度 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(), //每个点开始的位置 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(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+(e-s)/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],((e-s)/360*100).toFixed(0)+'%') }) .on('mouseout',function(e){ var elem = e.toElement || e.relatedTarget; //如果碰到里面的文本 或者是提示框 不消失 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; var name = o.name, size = calTextLen(name), dot = angle(radiu,[rx,ry],s+(e-s)/2,2), showDot = angle(radiu- Rpice * i,[rx,ry],s+(e-s)/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:((e-s)/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), (x-r).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), (y-r).toFixed(0), L, (x+r).toFixed(0), y.toFixed(0), x.toFixed(0), (y+r).toFixed(0), (x-r).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: [ '一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月' ] }, 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>