HTML canves 饼图2

在上一个框架上修改的另外一种战绩展示饼图

源代码:

  1 //饼图
  2 var pieChart = {  
  3     width: 600,  
  4     height: 400,  
  5     series: [],  
  6     unit: "场",  
  7     chartCanvas: null,  
  8     selectable : true,  
  9     title: "Pie Chart",  
 10     legend : {  
 11         enable : true  
 12     },  
 13     edge : {  
 14         width: 10,  
 15         height: 10  
 16     },  
 17     animation: {  
 18         enable: true,  
 19         animCanvas : null,  
 20         hh: 1, // trick is here!! for animation play  
 21         pctx: null  
 22     },  
 23     tooltips: {  
 24         enable: true,  
 25         tooltipCanvas : null,  
 26         ttContext: null,  
 27         index: -1  
 28     },  
 29     circle : {  
 30         cx: 0,  
 31         cy: 0,  
 32         radius: 0  
 33           
 34     },  
 35     text : {  
 36         enable: false,  
 37         content:[]  
 38     },  
 39       
 40     init: function (config) {  
 41         this.chartCanvas = config.canvas;  
 42         this.chartCanvas.width = config.width;  
 43         this.chartCanvas.height = config.height;  
 44         this.width = config.width ;  
 45         this.height = config.height ;  
 46         this.series = config.series;  
 47         this.title = config.title;  
 48         this.unit = config.unit;  
 49         this.count =  config.count;
 50         this.max = config.max;
 51         this.shadow = config.shadow;
 52         
 53         var ctx = this.chartCanvas.getContext("2d");  
 54         this.devicePixelRatio = window.devicePixelRatio || 1;
 55         this.backingStoreRatio = ctx.webkitBackingStorePixelRatio ||
 56                             ctx.mozBackingStorePixelRatio ||
 57                             ctx.msBackingStorePixelRatio ||
 58                             ctx.oBackingStorePixelRatio ||
 59                             ctx.backingStorePixelRatio || 1;
 60         this.devicePixelRatio = this.devicePixelRatio/this.backingStoreRatio;
 61         this.chartCanvas.height = this.height * this.devicePixelRatio;
 62         this.chartCanvas.width = this.width * this.devicePixelRatio;
 63         
 64         this.chartCanvas.style.height = this.height  + "px";
 65         this.chartCanvas.style.width = this.width  + "px";
 66         this.width = config.width * this.devicePixelRatio-5* this.devicePixelRatio;  
 67         this.height = config.height * this.devicePixelRatio;  
 68         this.edge.width = 40 * this.devicePixelRatio;
 69         this.edge.height = 40 * this.devicePixelRatio;
 70         if(config.tooltips != undefined) {  
 71             this.tooltips.enable = config.tooltips.enable;            
 72         }  
 73         if(config.animation != undefined) {  
 74             this.animation.enable = config.animation.enable;              
 75         }  
 76         if(config.legend != undefined) {  
 77             this.legend.enable = config.legend.enable;            
 78         }  
 79         if(config.text != undefined) {  
 80             this.text.enable = config.text.enable;  
 81         }
 82         this.render();
 83     },  
 84       
 85     render : function() {  
 86         // initialization circle  
 87         this.circle.cx = this.width/3.8;  
 88         this.circle.cy = this.height/2;  
 89         this.circle.radius = Math.min(this.width/2.4, this.height/2.4) - 12*this.devicePixelRatio;  
 90         var ctx = null;  
 91         if(this.animation.enable) {  
 92             this.animation.animCanvas = document.createElement("canvas");  
 93             this.animation.animCanvas.width = this.width;  
 94             this.animation.animCanvas.height = this.height;  
 95             ctx = this.animation.animCanvas.getContext("2d");  
 96         } else {  
 97             ctx = this.chartCanvas.getContext("2d");  
 98             this.renderBorder(ctx);  
 99         }  
100           
101         if(this.circle.radius <= 0) {  
102             ctx.strokeText("Can not reader the chart, Circle is too small.");  
103             return;  
104         }  
105           
106         // draw each arc according to data series   
107         var sum = 0;  
108         var nums = this.series.length;  
109         for(var i=0; i<nums; i++) {  
110             sum += this.series[i].value;  
111         }  
112           
113         // draw title    
114         var pt = 18*this.devicePixelRatio;
115         ctx.font = pt+'px Microsoft YaHeii'; 
116         ctx.fillText(this.title, this.width/2 - this.edge.width, 30);  
117         ctx.save();  
118         var deltaArc = 0;  
119         for(var i=0; i<nums; i++) {  
120             var precent = this.series[i].value/sum;  
121             this.renderPie(ctx, i, precent, deltaArc);  
122             deltaArc += 2*Math.PI * precent;  
123         }  
124         ctx.restore();  
125        
126         if(this.shadow){
127             // add blur shadow  
128             ctx.save();  
129             ctx.shadowColor = "black";  
130             ctx.shadowOffsetX = 0;  
131             ctx.shadowOffsetY = 0;  
132             ctx.shadowBlur = 10;  
133             ctx.beginPath();  
134             ctx.arc(this.circle.cx, this.circle.cy, this.circle.radius, 0, Math.PI * 2, false);  
135             ctx.closePath();  
136             ctx.lineWidth = 1;  
137             ctx.strokeStyle = "RGBA(127,127,127,1)";  
138             ctx.stroke();  
139             ctx.restore(); 
140         }
141         
142         // 画内部空白  
143         ctx.beginPath();  
144         ctx.moveTo(this.circle.cx, this.circle.cy);  
145         ctx.arc(this.circle.cx, this.circle.cy, this.circle.radius*0.25, 0, Math.PI * 2, true);  
146         ctx.closePath();  
147         ctx.fillStyle = 'rgba(255,255,255,1)';  
148         ctx.fill();  
149         
150         ctx.moveTo(this.circle.cx-10*this.devicePixelRatio, this.circle.cy);  
151         ctx.font = 'bold 12px 微软雅黑';    //斜体 30像素 微软雅黑字体  
152         var pt = 12*this.devicePixelRatio;
153         ctx.font = pt+'px Microsoft YaHeii'; 
154         ctx.fillStyle = "black"; //"#000000";  
155         var percent = this.count+this.unit;
156             ctx.fillText(percent,this.circle.cx-10*this.devicePixelRatio, this.circle.cy+5*this.devicePixelRatio);  
157         
158         // render legend  
159         ctx.save();  
160         this.renderLegend(ctx, sum);  
161         ctx.restore();  
162           
163         // play animation  
164         if(this.animation.enable) {  
165             var parent = this;  
166             this.animation.pctx = this.chartCanvas.getContext("2d");  
167             this.renderBorder(this.animation.pctx);  
168            setTimeout(function(){ parent.playAnimation(parent);},0)                
169         }  
170     },  
171       
172     showTooltips : function(loc, ctx) {  
173         if(!this.tooltips.enable) {  
174             return;  
175         }  
176         var dx = loc.x - this.width/2;  
177         var dy = loc.y - this.height/2;  
178         var dis = Math.floor(Math.sqrt(dx * dx + dy * dy));  
179         if(dis <= this.circle.radius) {  
180             // draw tool tip text  
181             var angle = Math.atan2(dy,dx);  
182             if(angle <= 0) {  
183                 // if[-Math.PI, 0], make it[Math.PI, 2*Math.PI]  
184                 angle = angle + 2*Math.PI;  
185             }  
186               
187             var sum = 0;  
188             var nums = this.series.length;  
189             for(var s=0; s<nums; s++) {  
190                 sum += this.series[s].value;  
191             }  
192               
193             var deltaArc = 0;  
194             var index = 0;  
195             for(var i=0; i<nums; i++) {  
196                 var precent = this.series[i].value/sum;  
197                 deltaArc += 2*Math.PI * precent;  
198                 if(angle<=deltaArc) {  
199                     index = i;  
200                     break;  
201                 }  
202             }  
203             if(this.tooltips.tooltipCanvas == null) {  
204                 this.tooltips.tooltipCanvas = document.createElement("canvas");  
205                 this.tooltips.ttContext = this.tooltips.tooltipCanvas.getContext("2d");  
206                 this.tooltips.tooltipCanvas.width = 150;  
207                 this.tooltips.tooltipCanvas.height = 100;  
208             }   
209               
210             // only draw once  
211             // if(index == this.tooltips.index){  
212             //  return;  
213             // }  
214             this.clearTooltips(ctx);  
215               
216             this.tooltips.index = index;  
217             var m_context = this.tooltips.ttContext;  
218             m_context.save();  
219             m_context.clearRect(0, 0, this.tooltips.tooltipCanvas.width, this.tooltips.tooltipCanvas.height);  
220             m_context.lineWidth = 2;  
221             m_context.strokeStyle = this.series[index].color;  
222             m_context.fillStyle="RGBA(255,255,255,0.7)";  
223             // m_context.strokeRect(2, 2, this.tooltips.tooltipCanvas.width-4, this.tooltips.tooltipCanvas.height-4);  
224             // m_context.fillRect(2,2,this.tooltips.tooltipCanvas.width-4, this.tooltips.tooltipCanvas.height-4);   
225             //m_context.font="14px Arial";  
226             var pt = 14*this.devicePixelRatio;
227             m_context.font = pt+'px Microsoft YaHeii'; 
228             m_context.fillStyle="RGBA(0,0,0,1)";   
229             m_context.fillText(this.series[index].name + ": " + this.series[index].value + this.unit, 5, 40);   
230             m_context.restore();  
231               
232             // make tool-tip rectangle is always visible   
233             if((loc.x + this.tooltips.tooltipCanvas.width)> this.width) {  
234                 loc.x = loc.x - this.tooltips.tooltipCanvas.width;  
235             }  
236             if((loc.y - this.tooltips.tooltipCanvas.height) <= 0) {  
237                 loc.y = loc.y + this.tooltips.tooltipCanvas.height;  
238             }  
239             ctx.drawImage(this.tooltips.tooltipCanvas, 0, 0, this.tooltips.tooltipCanvas.width, this.tooltips.tooltipCanvas.height,   
240                     loc.x, loc.y-this.tooltips.tooltipCanvas.height, this.tooltips.tooltipCanvas.width, this.tooltips.tooltipCanvas.height);      
241         } else {  
242             this.tooltips.index = -1;  
243             this.clearTooltips(ctx);  
244         }  
245     },  
246       
247     clearTooltips : function(ctx) {  
248         ctx.clearRect(0,0,this.width, this.height);  
249         this.renderBorder(ctx);  
250         ctx.drawImage(this.animation.animCanvas, 0, 0, this.width, this.height, 0, 0, this.width, this.height);   
251     },  
252       
253     renderBorder : function(ctx) { 
254         //canvas 边框
255         //ctx.save();  
256         //ctx.fillStyle="white";  
257         //ctx.strokeStyle="black";  
258         //ctx.fillRect(0, 0, this.width, this.height);  
259         //ctx.strokeRect(0, 0, this.width, this.height);  
260         //ctx.restore();  
261     },  
262       
263     renderPie : function(ctx, index, precent, deltaArc) {  
264         var endAngle = deltaArc + 2*Math.PI*precent; 
265         ctx.save();
266         ctx.lineWidth=this.devicePixelRatio;
267         ctx.beginPath();  
268         ctx.arc(this.circle.cx, this.circle.cy, this.circle.radius, deltaArc, endAngle, false);  
269         ctx.moveTo(this.circle.cx, this.circle.cy);  
270         ctx.lineTo(this.circle.cx + this.circle.radius * Math.cos(deltaArc), this.circle.cy + this.circle.radius * Math.sin(deltaArc));  
271         ctx.lineTo(this.circle.cx + this.circle.radius * Math.cos(endAngle), this.circle.cy + this.circle.radius * Math.sin(endAngle));  
272         ctx.lineTo(this.circle.cx, this.circle.cy);  
273         ctx.closePath();  
274         ctx.fillStyle = this.series[index].color;  
275         ctx.fill();  
276         ctx.restore();
277         //画扇形
278         var avgAngle = (endAngle - deltaArc)/2;
279         var _deltaArc = deltaArc;
280         var _endAngle = endAngle;
281         var _circlex = this.circle.cx+this.circle.radius+(this.width/5)*this.devicePixelRatio;
282         var _circley = index*(this.height/3.5)*this.devicePixelRatio + this.edge.height*1.7*this.devicePixelRatio;
283         var _radius = this.circle.radius/3;
284         ctx.fillStyle = this.series[index].color;
285         ctx.sector(_circlex,_circley,_radius,_deltaArc,_endAngle,false).fill();
286         
287         ctx.beginPath();
288         ctx.strokeStyle = "#CCC5C5";
289         ctx.arc(_circlex,_circley,_radius,0,Math.PI*2);
290         ctx.stroke();
291         
292         var size = this.text.content.length;  
293         var tipStr = this.series[index].tips;  
294         var pt = 10*this.devicePixelRatio;
295         ctx.font = pt+'pt Microsoft YaHeii'; 
296         ctx.textAlign="left";
297         var textArr = tipStr.split(",");
298         for(var textIndex = 0; textIndex < textArr.length;textIndex++){
299             ctx.fillStyle = "#666";
300             ctx.fillText(textArr[textIndex],_circlex+_radius+10*this.devicePixelRatio,_circley-((textArr.length-1)*10*this.devicePixelRatio)+20*this.devicePixelRatio*textIndex);
301         }
302         
303         // 渲染文字
304         if(this.text.enable) {   
305             var halfEndAngle = deltaArc + Math.PI*precent;  
306             var hx = this.circle.cx + this.circle.radius * Math.cos(halfEndAngle);  
307             var hy = this.circle.cy + this.circle.radius * Math.sin(halfEndAngle);  
308               
309             var avgx = Math.abs(hx - this.circle.cx)/2;
310             var avgy = Math.abs(hy - this.circle.cy)/2;
311             var textPos = (hx < this.circle.cx) ? (hx - this.edge.width)*0.9 : (hx + this.edge.width)*1.1;  
312             var textPosX = (hx < this.circle.cx) ? hx + avgx: hx - avgx;  
313             var textPosY = (hy < this.circle.cy) ? hy + avgy : hy - avgy;
314             precent = Math.round (precent*100) / 100;  
315             var size = this.text.content.length;  
316             var tipStr = (size > index) ? this.text.content[index] : this.series[index].name + ": " + ((this.series[index].value/this.count)*100).toFixed(0) + "%";  
317             var pt = 12*this.devicePixelRatio;
318             ctx.font = pt+'pt Microsoft YaHeii';  
319             
320             //给圆环加文本
321             ctx.fillStyle="white";  
322             
323             ctx.textAlign="center";
324             if(this.series[index].value > 0)ctx.fillText(tipStr, textPosX, textPosY);
325         }  
326     },  
327       
328     renderLegend : function(ctx, sum) {  
329         if(!this.legend.enable) return;  
330         var nums = this.series.length;  
331         var pt = 12*this.devicePixelRatio;
332         ctx.font = pt+'px Microsoft YaHeii';  
333         var pos = (this.width/2 > (this.circle.radius+50 * this.devicePixelRatio)) ? 50*this.devicePixelRatio : (this.circle.cx - this.circle.radius);  
334         for(var i=0; i<nums; i++) {  
335             var x = this.series[i].value/sum;  
336             x = Math.round (x*100) / 100;  
337             var tipStr =  this.series[i].name + ": " + this.series[i].value + "场";  
338             this.series[i].precent = tipStr;  
339             ctx.fillStyle = this.series[i].color;  
340             ctx.fillRect((pos - 40*this.devicePixelRatio), (20*i+10) * this.devicePixelRatio, 10 * this.devicePixelRatio, 10 * this.devicePixelRatio);  
341             ctx.fillStyle = "black";  
342             ctx.fillText(tipStr, (pos - 25*this.devicePixelRatio), (20*i+20) * this.devicePixelRatio);  
343         }         
344     },  
345       
346     playAnimation : function(parent) {    
347         if(parent.animation.hh < parent.height) {  
348             parent.animation.pctx.save();  
349             parent.animation.pctx.globalAlpha=0.5;  
350             parent.animation.pctx.clearRect(0,0,parent.width, parent.height);  
351             parent.renderBorder(parent.animation.pctx);  
352             parent.animation.pctx.drawImage(parent.animation.animCanvas, 0, 0, parent.width, this.animation.hh, 0, 0, parent.width, this.animation.hh);  
353             parent.animation.hh = parent.animation.hh + 10;  
354             parent.animation.pctx.restore();                      
355             setTimeout(function() {parent.playAnimation(parent);}, 0);   
356         } else {  
357             parent.animation.pctx.clearRect(0,0,parent.width, parent.height);  
358             parent.renderBorder(parent.animation.pctx);  
359             parent.animation.pctx.drawImage(parent.animation.animCanvas, 0, 0, parent.width, parent.height, 0, 0, parent.width, parent.height);  
360               
361             // enable tool-tip functionality  
362             if(parent.animation.enable && parent.legend.enable) {  
363                 parent.chartCanvas.addEventListener('mousemove', function(event) {  
364                     var x = event.pageX;  
365                     var y = event.pageY;  
366                     var canvas = event.target;  
367                     var bbox = canvas.getBoundingClientRect();  
368                     var loc = { x: x - bbox.left * (canvas.width  / bbox.width),  
369                             y: y - bbox.top  * (canvas.height / bbox.height)};  
370                       
371                     parent.showTooltips(loc, (parent.animation.enable ? parent.animation.pctx : ctx));  
372                 }, false);  
373             }  
374         }  
375     }
376       
377 };
378 //扇形
379 CanvasRenderingContext2D.prototype.sector = function (x, y, radius, sDeg, eDeg,fx) {
380   // 初始保存
381   this.save();
382   // 位移到目标点
383   this.translate(x, y);
384   this.beginPath();
385   // 画出圆弧
386   this.arc(0,0,radius,sDeg, eDeg,fx);
387   // 再次保存以备旋转
388   this.save();
389   // 旋转至起始角度
390   this.rotate(eDeg);
391   // 移动到终点,准备连接终点与圆心
392   this.moveTo(radius,0);
393   // 连接到圆心
394   this.lineTo(0,0);
395   // 还原
396   this.restore();
397   // 旋转至起点角度
398   this.rotate(sDeg);
399   // 从圆心连接到起点
400   this.lineTo(radius,0);
401   this.closePath();
402   // 还原到最初保存的状态
403   this.restore();
404   return this;
405 }
View Code

调用方式:

 1 var canvas = document.getElementById("myCanvas");  
 2         var seriesData = [{name:"胜", value:5, color:"#ec362c",tips:"主胜概率:74.78%,1.主赔<客赔,2. 主强且主胜,水位下降,低于初盘达2.56%"},  
 3                       {name:"平", value:3, color:"#b3b3b3",tips:"主平概率:12.61%,1. 平赔:7"},  
 4                       {name:"负", value:1, color:"#599bee",tips:"主负概率:12.61%,1. 平赔:14"}]  
 5         var config = {  
 6                 width : 600 ,   
 7                 height: 400,  
 8                 series: seriesData,  
 9                 canvas: canvas,
10                 count:8,
11                 max:0,
12                 unit: "场",  
13                 title:"", 
14                 shadow:false, 
15                 legend : {  
16                     enable : false  
17                 },  
18                 text : {  
19                     enable: true  
20                 },  
21         };  
22         pieChart.init(config); 
View Code

最终效果:

posted @ 2015-10-14 16:01  xk911  阅读(257)  评论(0)    收藏  举报