绘制扇形
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> canvas { border: 1px solid #ccc; } </style> </head> <body> <canvas width="600" height="400"></canvas> <script> var myCanvas = document.querySelector('canvas'); var ctx = myCanvas.getContext('2d'); /*在中心位置画一个半径150px的圆弧右上角 扇形 边 填充 */ var w = ctx.canvas.width; var h = ctx.canvas.height; /*把起点放到圆心位置*/ ctx.moveTo(w/2,h/2); ctx.arc(w/2,h/2,150,0,-Math.PI/2,true); /*闭合路径*/ //ctx.closePath(); ctx.fill(); </script> </body> </html>
绘制数据饼图
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> canvas { border: 1px solid #ccc; } </style> </head> <body> <canvas width="600" height="400"></canvas> <script> var myCanvas = document.querySelector('canvas'); var ctx = myCanvas.getContext('2d'); /*1.根据37期的年龄分布绘制饼图*/ /*2.准备统计的数据*/ /*15-20岁 6个*/ /*20-25岁 30个*/ /*25-30岁 10个*/ /*30-35岁 8个*/ var data = [6, 30, 10, 8]; /*3.在饼图表示出来*/ /*4.需要把数据转出弧度*/ var angleList = []; var total = 0; data.forEach(function (item, i) { total += item; }); console.log(total); /*第二是转换成弧度的时候就可以去绘制扇形 减少一次遍历*/ data.forEach(function (item, i) { var angle = Math.PI * 2 * (item/total); angleList.push(angle); }); console.log(angleList); /*5.根据弧度绘制扇形*/ var w = ctx.canvas.width; var h = ctx.canvas.height; var x0 = w/2; var y0 = h/2; /*获取随机颜色*/ var 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 startAngle = 0; angleList.forEach(function (item,i) { /*上一次绘制的结束弧度等于当前次的起始弧度*/ var endAngle = startAngle + item; ctx.beginPath(); ctx.moveTo(x0,y0); ctx.arc(x0,y0,150,startAngle,endAngle); ctx.fillStyle = getRandomColor(); ctx.fill(); /*记录当前的结束位置作为下一次的起始位置*/ startAngle = endAngle; }); </script> </body> </html>
绘制文本
- ctx.font = ‘微软雅黑’ 设置字体
- strokeText()
- fillText(text,x,y,maxWidth)
text 要绘制的文本
x,y 文本绘制的坐标(文本左下角)
maxWidth 设置文本最大宽度,可选参数
- ctx.textAlign文本水平对齐方式,相对绘制坐标来说的
left
center
right
start 默认
end
- ctx.direction属性css(rtl ltr) start和end于此相关
如果是ltr,start和left表现一致
如果是rtl,start和right表现一致
- ctx.textBaseline 设置基线(垂直对齐方式 )
top 文本的基线处于文本的正上方,并且有一段距离
middle 文本的基线处于文本的正中间
bottom 文本的基线处于文本的证下方,并且有一段距离
hanging 文本的基线处于文本的正上方,并且和文本粘合
alphabetic 默认值,基线处于文本的下方,并且穿过文字
ideographic 和bottom相似,但是不一样
- measureText() 获取文本宽度obj.widt
案例:画布中心绘制文字
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> canvas { border: 1px solid #ccc; display: block; margin: 100px auto; } </style> </head> <body> <canvas width="600" height="400"></canvas> <script> var myCanvas = document.querySelector('canvas'); var ctx = myCanvas.getContext('2d'); /*1.在画布的中心绘制一段文字*/ /*2.申明一段文字*/ var str = '您吃饭中饭了吗'; /*3.确定画布的中心*/ var w = ctx.canvas.width; var h = ctx.canvas.height; /*4.画一个十字架在画布的中心*/ ctx.beginPath(); ctx.moveTo(0, h / 2 - 0.5); ctx.lineTo(w, h / 2 - 0.5); ctx.moveTo(w / 2 - 0.5, 0); ctx.lineTo(w / 2 - 0.5, h); ctx.strokeStyle = '#eee'; ctx.stroke(); /*5.绘制文本*/ ctx.beginPath(); ctx.strokeStyle = '#000'; var x0 = w/2; var y0 = h/2; /*注意:起点位置在文字的左下角*/ /*有文本的属性 尺寸 字体 左右对齐方式 垂直对齐的方式*/ ctx.font = '40px Microsoft YaHei'; /*左右对齐方式 (center left right start end) 基准起始坐标*/ ctx.textAlign = 'center'; /*垂直对齐的方式 基线 baseline(top,bottom,middle) 基准起始坐标*/ ctx.textBaseline = 'middle'; //ctx.direction = 'rtl'; //ctx.strokeText(str,x0,y0); ctx.fillText(str,x0,y0); /*6.画一个下划线和文字一样长*/ ctx.beginPath(); /*获取文本的宽度*/ console.log(ctx.measureText(str)); var width = ctx.measureText(str).width; ctx.moveTo(x0-width/2,y0 + 20); ctx.lineTo(x0+width/2,y0 + 20); ctx.stroke(); </script> </body> </html>
圆与文本综合案例:数据饼状图
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> canvas { border: 1px solid #ccc; display: block; margin: 100px auto; } </style> </head> <body> <canvas width="600" height="400"></canvas> <script> /*var myCanvas = document.querySelector('canvas'); var ctx = myCanvas.getContext('2d');*/ /*1.绘制饼状态图*/ /*1.1 根据数据绘制一个饼图*/ /*1.2 绘制标题 从扇形的弧中心伸出一条线在画一条横线在横线的上面写上文字标题*/ /*1.3 在画布的左上角 绘制说明 一个和扇形一样颜色的矩形 旁边就是文字说明*/ var PieChart = function (ctx) { /*绘制工具*/ 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 + 60; this.y0 = this.h / 2; /*半径*/ this.radius = 150; /*伸出去的线的长度*/ this.outLine = 20; /*说明的矩形大小*/ this.rectW = 30; this.rectH = 16; this.space = 20; } PieChart.prototype.init = function (data) { /*1.准备数据*/ this.drawPie(data); }; PieChart.prototype.drawPie = function (data) { var that = this; /*1.转化弧度*/ var angleList = this.transformAngle(data); /*2.绘制饼图*/ var startAngle = 0; angleList.forEach(function (item, i) { /*当前的结束弧度要等于下一次的起始弧度*/ var endAngle = startAngle + item.angle; that.ctx.beginPath(); that.ctx.moveTo(that.x0, that.y0); that.ctx.arc(that.x0, that.y0, that.radius, startAngle, endAngle); var color = that.ctx.fillStyle = that.getRandomColor(); that.ctx.fill(); /*下一次要使用当前的这一次的结束角度*/ /*绘制标题*/ that.drawTitle(startAngle, item.angle, color , item.title); /*绘制说明*/ that.drawDesc(i,item.title); startAngle = endAngle; }); }; PieChart.prototype.drawTitle = function (startAngle, angle ,color , title) { /*1.确定伸出去的线 通过圆心点 通过伸出去的点 确定这个线*/ /*2.确定伸出去的点 需要确定伸出去的线的长度*/ /*3.固定伸出去的线的长度*/ /*4.计算这个点的坐标*/ /*5.需要根据角度和斜边的长度*/ /*5.1 使用弧度 当前扇形的起始弧度 + 对应的弧度的一半 */ /*5.2 半径+伸出去的长度 */ /*5.3 outX = x0 + cos(angle) * ( r + outLine)*/ /*5.3 outY = y0 + sin(angle) * ( r + outLine)*/ /*斜边*/ var edge = this.radius + this.outLine; /*x轴方向的直角边*/ var edgeX = Math.cos(startAngle + angle / 2) * edge; /*y轴方向的直角边*/ var edgeY = Math.sin(startAngle + 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; /*画文字和下划线*/ /*线的方向怎么判断 伸出去的点在X0的左边 线的方向就是左边*/ /*线的方向怎么判断 伸出去的点在X0的右边 线的方向就是右边*/ /*结束的点坐标 和文字大小*/ this.ctx.font = '14px Microsoft YaHei'; var textWidth = this.ctx.measureText(title).width ; if(outX > this.x0){ /*右*/ this.ctx.lineTo(outX + textWidth,outY); this.ctx.textAlign = 'left'; }else{ /*左*/ this.ctx.lineTo(outX - textWidth,outY); this.ctx.textAlign = 'right'; } this.ctx.stroke(); this.ctx.textBaseline = 'bottom'; this.ctx.fillText(title,outX,outY); }; PieChart.prototype.drawDesc = function (index,title) { /*绘制说明*/ /*矩形的大小*/ /*距离上和左边的间距*/ /*矩形之间的间距*/ this.ctx.fillRect(this.space,this.space + index * (this.rectH + 10),this.rectW,this.rectH); /*绘制文字*/ this.ctx.beginPath(); this.ctx.textAlign = 'left'; this.ctx.textBaseline = 'top'; this.ctx.font = '12px Microsoft YaHei'; this.ctx.fillText(title,this.space + this.rectW + 10 , this.space + index * (this.rectH + 10)); }; PieChart.prototype.transformAngle = function (data) { /*返回的数据内容包含弧度的*/ 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; }; PieChart.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: 30 }, { title: '25-30岁', num: 10 }, { title: '30以上', num: 8 } ]; var pieChart = new PieChart(); pieChart.init(data); </script> </body> </html>