效果展示:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> canvas { border:1px solid red; display: block; margin: 100px auto; } </style> </head> <body> <canvas width="600px" height="400px"></canvas> <script> var myCanvas = document.querySelector('canvas'); var ctx = myCanvas.getContext('2d'); //构造函数 function pieChar () { //宽高,原点,半径 this.ctx = ctx || document.querySelector('canvas').getContext('2d'); this.w = this.ctx.canvas.width; this.h = this.ctx.canvas.height; this.x0 = this.w / 2 +10; this.y0 = this.h / 2 +10; this.radius = 150; } //初始化方法 pieChar.prototype.init = function(){ this.drawPie(); this.drawTitle(); this.drawDisc(); } //画扇形 pieChar.prototype.drawPie = function(data){ var angleList = this.transformAngle(data); var angleStart = 0; var that = this; angleList.forEach(function(item,i){ that.ctx.beginPath(); that.ctx.moveTo(that.x0,that.y0); var angleEnd = angleStart + item.angle; that.ctx.arc(that.x0,that.y0,that.radius,angleStart,angleEnd); var color = that.getRandomColor(); that.ctx.fillStyle = color; that.ctx.fill(); that.drawDisc(angleStart,item.angle,color,item.title); that.drawTitle(i,item.title); angleStart = angleEnd; }) } //画文字 pieChar.prototype.drawTitle = function(index,title){ var rectW = 30; var rectH = 16; var space = 10; this.ctx.fillRect(space,space+index*(rectH + space),rectW,rectH); this.ctx.beginPath(); this.ctx.textAlign = 'left'; this.ctx.textBaseline = 'top'; this.ctx.fillText(title,space+rectW+10,space+index*(rectH + space)); } //描述 pieChar.prototype.drawDisc = function(angleStart,angle,color,title){ //确定伸出去的线,中心点和伸出去的点 //确定伸出去的线的长度 var outline = 20; edge = this.radius +outline; var edgeX = Math.cos(angleStart + angle / 2) * edge; var edgeY = Math.sin(angleStart + angle / 2) * edge; var outX = this.x0 + edgeX; var outY = this.y0 + edgeY; this.ctx.beginPath(); this.ctx.moveTo(this.x0,this.y0); this.ctx.lineTo(outX,outY); this.ctx.strokeStyle = color; this.ctx.font = '16px Microsoft YaHei'; var textW = this.ctx.measureText(title).width; if (outX > this.x0) { this.ctx.lineTo(outX+textW,outY); this.ctx.textAlign = 'left'; }else { this.ctx.lineTo(outX - textW,outY); this.ctx.textAlign = 'right'; } this.ctx.stroke(); this.ctx.textBaseline = 'bottom'; this.ctx.fillText(title,outX,outY); } pieChar.prototype.transformAngle= function(){ var total = 0; data.forEach(function(item,i){ total+=item.num; }); data.forEach(function(item,i){ var angle = item.num / total * Math.PI * 2; item.angle = angle; }); return data; } pieChar.prototype.getRandomColor = function(){ var r = Math.floor(Math.random()*256); var g = Math.floor(Math.random()*256); var b = Math.floor(Math.random()*256); return 'rgb('+ r +','+ g +','+ b +')'; } var data = [{ title:'15-20岁', num:6 },{ title:'20-25岁', num:20 },{ title:'25-30岁', num:16 },{ title:'30-35岁', num:10 }]; var pie = new pieChar(); pie.init(); </script> </body> </html>