一、绘制矩形
1、rect (x, y, width, height) : 绘制矩形的路径
---用轨迹画的,不是独立路径( 没有beginPath() )
---需要stroke()描边才会显示
2、strokeRect (x, y, width, height) : 描边矩形
---自动描边,有独立路径
3、fillRect (x, y, width, height) : 填充矩形
---自动填充(默认黑色),有独立路径
4、clearRect (x, y, width, height) : 清除矩形
---相当于橡皮擦
var myCanvas = document.querySelector("canvas");
var ctx = myCanvas.getContext("2d");
ctx.fillRect(100, 100, 300, 200);
ctx.clearRect(100,100,50,50);
如下图:
5、绘制渐变矩形
---与css3差不多,渐变三要素 : 方向(有起始坐标, 结束坐标) 初始颜色 结束颜色
var myCanvas = document.querySelector("canvas");
var ctx = myCanvas.getContext("2d");
var linearGradient = ctx.createLinearGradient(100, 100, 400, 300);
linearGradient.addColorStop(0, 'yellow');
linearGradient.addColorStop(.5, 'pink');
linearGradient.addColorStop(1, 'red');
ctx.fillStyle = linearGradient;
ctx.fillRect(100, 100, 300, 200);
如下图:
二、绘制扇形
1、圆弧
(1)什么是弧度???
--- 一种长度的描述单位
--- 一弧度的长等于圆的半径的长
--- 一个圆有 2π个弧度
--- 一个角度等于 π / 180 个弧度
--- 90度等于 π / 2个弧度
2、绘制圆弧
(1)确定圆心(坐标)
(2)确定半径
(3)确定 起始绘制 和 结束绘制 的位置 ,弧的位置 --- startAngle , endAngle
(4)确定绘制的方向,默认是顺时针(false),逆时针(true)
(5)绘制圆弧的函数 ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise)
例:在中心位置画一个半径为150px的圆弧 ,0度到90度位置的圆弧
var w = ctx.canvas.width;
var h = ctx.canvas.height;
ctx.arc(x / 2, h / 2, 150, 0 , Math.PI / 2);
ctx.stroke();
3、绘制扇形
//第一种
//先移动原点到中心点
ctx.moveTo(w / 2, h / 2);
//绘制圆弧时其实绘制了两条轨迹
ctx.arc(w / 2, h / 2, 150, Math.PI / 2, Math.PI);
//闭合路径
ctx.closrPath();
ctx.stroke();
//第二种
//先绘制圆弧
ctx.arc(w / 2, h / 2, 150, Math.PI / 2, Math.PI);
//绘制一条到中心点的轨迹
ctx.lineTo(w / 2, h / 2);
//闭合路径
ctx.closePath();
ctx.stroke();
三、绘制n等分的随机颜色的圆
var myCanvas = document.querySelector("canvas");
var ctx = myCanvas.getContext("2d");
//确认中心点X
var x0 = ctx.canvas.width / 2;
//确认中心点Y
var h0 = ctx.canvas.height / 2;
//绘制多少个扇形
var num = 6;
//获取扇形的角度
var angle = 2 * Math.PI / num;
//随机颜色函数
var randomColor = 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+")";
}
for(var i = 0; i < num; i++){
//获取每一次的起始位置
var stratAngle = i * angle;
//获取每一次的结束位置
var endAngle = (i + 1) * angle;
ctx.beginPath();
ctx.moveTo(x0, h0);
ctx.arc(x0, h0, 150, stratAngle, endAngle);
ctx.fillStyle = randomColor();
ctx.fill();
}
四、绘制带数据的饼图
var myCanvas = document.querySelector("canvas");
var ctx = myCanvas.getContext("2d");
var x0 = ctx.canvas.width / 2;
var y0 = ctx.canvas.height / 2;
// 自定义了四个数组
var data = [8,30,19,12];
var angleList = [];
var total = 0;
data.forEach(function(item,i){
total += item;
if(i == data.length -1){
angleList.push(2 * Math.PI * (data[0] / total));
}
});
// 计算4个数据分别占弧度的比例,加入angleList中
data.forEach(function(item,i){
if(i >= 1){
angleList.push(2 * Math.PI * (item / total));
}
})
var randomColor = 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 = randomColor();
ctx.fill();
// 开始弧度是上一次的结束弧度
startAngle = endAngle;
})
五、画布中绘制文字
1、 strokeText (str, x, y) : 绘制描边文本
2、fillText(str, x, y) : 绘制填充文本
注:起始坐标位于左下角
3、font = ‘ size, family‘ : 设置文本的大小和字体(第一个参数是大小,第二个参数是字体)
例:ctx.font = ' 40px, Microsoft YaHei ' ;
4、textAlign = left, center, right, start(默认), end : 设置文本水平方向的对齐方式
5、textBaseline = top , middle, bottom : 设置文本垂直方向的对齐方式
6、measureText(str) :获取文本的宽度
六、绘制饼图加标题和说明
---绘制完饼图,别人根本看不懂那一块是那一块,所以需要加上标题和说明
---从扇形的弧中间伸出一条线,在画一条横线,在横线上写上文字标题
---在画布的左上角,绘制一个和扇形一样颜色的矩形说明,旁边附上文字说明
如:
1、绘制扇形中间伸出来的线
1.1---如何确定这条线的位置 :两点确定一条 —— 中心点和线末端的点
1.2---如何确定末端的点 :
如上图:可以把它看成一个直角三角形,则 X1 = X0 + a ; Y1 = Y0 + b ;
1.3---那么又如何确定 a 和 b 的长度呢?
这时需要用到三角函数的勾股定理,看下图:
已知 c = 1, 则 a = cos ( 30° ) * c
b = sin ( 30° ) * c
1.4---现在知道了 a 和 b 怎么求了,那么弧度又如何求呢?
由前面知道了弧度等于 比例 * 2π
而这里的弧度等于 : 开始弧度 + 当前弧度 / 2;
startAnglr + angle / 2;
所以 X1 = X0 + cos( startAngle + angle / 2 ) * radius
Y1 = X0 + sin( startAngle + angle / 2 ) * radius
1.5---代码
// 创建饼图对象 var PieChart = function(cavs){ this.ctx = document.querySelector("canvas").getContext("2d"); this.x0 = this.ctx.canvas.width / 2 + 60; this.y0 = this.ctx.canvas.height / 2; // 半径 this.radius = 150; // 标题伸出去的线的长度 this.outLine = 20 + this.radius; // 说明矩形的宽 this.rectW = 30; // 说明矩形的高 this.rectH = 16; // 说明矩形的左间距 this.space = 20; } // 初始化 PieChart.prototype.init = function(data){ this.drawPie(data); } // 绘制饼图函数 PieChart.prototype.drawPie = function(data){ var that = this; // 获取带有数据的数组,其中包含num,title,angle,ratio var angleList = this.transfromAngle(data); var startAngle = 0; angleList.forEach(function(item,i){ // 结束弧度等于开始弧度加上当前弧度 var endAngle = startAngle + item.angle; //绘制标题 that.drawTitle(startAngle,item.angle,item.title,item.ratio); that.ctx.beginPath(); that.ctx.moveTo(that.x0, that.y0); that.ctx.arc(that.x0, that.y0, that.radius, startAngle, endAngle); that.ctx.fillStyle = that.getRandomColor(); that.ctx.fill(); // 绘制说明 that.drawDescription(i,item.title); // 开始弧度等于上一次的结束弧度 startAngle = endAngle; }) } // 绘制标题函数 PieChart.prototype.drawTitle = function(startAngle,angle,title,ratio){ // 获取X方向线的长度,可以理解为a的长度 var outXLine = Math.cos(startAngle + angle / 2) * this.outLine; // 获取Y方向线的长度,可以理解为b的长度 var outYLine = Math.sin(startAngle + angle / 2) * this.outLine; // 获取末端点X坐标 var outX = this.x0 + outXLine; // 获取末端点Y坐标 var outY = this.y0 + outYLine; // 设置标题为 title加上ratio var str = title+" : "+ratio; this.ctx.beginPath(); this.ctx.moveTo(this.x0, this.y0); this.ctx.lineTo(outX, outY); // 设置标题垂直方向底线对齐 this.ctx.textBaseline = "bottom"; // 设置标题字体大小和字体 this.ctx.font = "14px Microsoft YaHei"; // 设置标题颜色 this.ctx.fillStyle = "#000"; // 如果末端点在中心点的右边,则横线向右,否则向左 if(outX >= this.x0){ this.ctx.lineTo(outX + this.ctx.measureText(str).width, outY); this.ctx.textAlign = 'left'; }else{ this.ctx.lineTo(outX - this.ctx.measureText(str).width, outY); // 设置文字水平对齐基于起始点的右边 this.ctx.textAlign = 'right'; } // 设置字体 this.ctx.fillText(str, outX, outY); this.ctx.stroke(); } PieChart.prototype.drawDescription = function(index,title){ // 1、矩形的大小 // 2、上边和左边的间距 // 3、矩形之间的间距 this.ctx.fillRect(this.space, this.space + index * (10 + this.rectH), 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 * (10 + this.rectH) + this.rectH / 4); } PieChart.prototype.transfromAngle = function(data){ var total = 0; // 获取数据总数 data.forEach(function(item,i){ total += item.num; }) data.forEach(function(item,i){ // 获取弧度并存如data中 item.angle = item.num / total * Math.PI * 2; // 获取百分比并精确到小数点后两位,存入data中 item.ratio = Math.round(item.num / total * 10000) / 100 + "%"; }) 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 = [ { num : 8, title : "15-20岁" }, { num : 30, title : "20-25岁" }, { num : 12, title : "25-30岁" }, { num : 16, title : "30-35岁" }, { num : 5, title : "35-40岁" }, ]; var pie = new PieChart(); pie.init(data);