[Canvas学习]绘制图形
学习目的:在Canvas上绘制矩形,三角形,直线,圆弧,曲线
栅格
栅格canvas grid,canvas元素默认被网格覆盖,栅格的起点是左上角坐标(0,0),元素的位置都是相对于栅格起点来定位的。
绘制矩形
API提供了三种方法绘制矩形
fillRect(x, y, width, height) 绘制填充的矩形
strokeRect(x, y, width, height) 绘制矩形边框
clearRect(x, y, width, height) 清除指定矩形区域变的完全透明
rect(x, y, width, height) 绘制矩形路径并将其添加到当前路径上
x和y是矩形左上角顶点相对于栅格原点的坐标
var canvas = document.getElementById("canvas");
if(canvas.getContext){
var ctx = canvas.getContext("2d");
ctx.fillRect(25,25,100,100); //画一个填充矩形
ctx.clearRect(45,45,60,60); //将其中一部分区域清除
ctx.strokeRect(50,50,50,50); //内部在绘制一个矩形边框
}
绘制路径
路径是通过不同颜色和宽度的线段或曲线相连形成的不同形状的点的集合。一个路径,甚至一个子路径都是闭合的。
绘制路径的步骤: 创建路径起始点,通过画图命令画出路径,再把路径封闭,最后通过描边或者填充来渲染图形。
beginPath() 新建一个路径,路径列表会清空,开始重新绘制图形。
closePath() 闭合路径
stroke() 绘制图形轮廓,路径不会自动闭合
fill() 填充路径内容区域,路径会自动闭合
moveTo(x, y) 仅仅移动笔触
lineTo(x, y) 绘制一条从当前位置到指定x,y位置的直线
var canvas = document.getElementById("canvas");
if(canvas.getContext){
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.moveTo(75,50);
ctx.lineTo(100,75);
ctx.lineTo(100,25);
ctx.fill();
}
/* fill()会自动闭合路径并填充,上面就是绘制了一个三角形 */
//体会moveTo()和storke()的区别
var canvas = document.getElementById("canvas");
if(canvas.getContext){
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.arc(75,75,50,0,Math.PI*2,true);
ctx.moveTo(110,75);
ctx.arc(75,75,35,0,Math.PI,false);
ctx.moveTo(65,65);
ctx.arc(60,65,5,0,Math.PI*2,true);
ctx.moveTo(95,65);
ctx.arc(90,65,5,0,Math.PI*2,true);
ctx.stroke();}
//moveTo()函数并不会绘制任何东西到canvas上,所以上面的实际效果就是绘制了一张笑脸。如果将moveTo()函数全部去掉,那么绘制的图形将是连续的,也就是会出现多个移动的线条。
绘制圆弧
arc(x, y, radius, startAngle, endAngle, anticlockwise) 绘制一个以x,y为圆心的以radius为半径的圆弧,从startAngle开始到endAngle结束,按照anticlockwise给定的方向来生成,默认是顺时针方向。弧度参数以x轴为基准,方向参数为布尔值,默认值是false表示顺时针方向。角度与弧度的转换关系 radians = (Math.PI/180)*degrees
arcTo(x1, y1, x2, y2, radius)根据给定的控制点和半径绘制一段圆弧,再以直线连接两个控制点
arcTo的理解:
*****在arcTo()方法之前,beginPath()产生路径或者通过其他方法操作后,Path肯定是有一个起始点或者当前点。再加上传入的两个参数坐标点,这时候坐标系上就会存在三个点。
有了这三个点,也就形成了连接三个点的两条直线。这时候arcTo()方法所绘制的圆弧是与这两条切线分别相切的。最后再以直线连接前面两个控制点,也就是连接路径起始点与x1,y1这两个点。
综合案例
var canvas = document.getElementById("canvas");
if(canvas.getContext){
var ctx = canvas.getContext("2d");
roundedRect(ctx,12,12,150,150,15);
roundedRect(ctx,19,19,150,150,9);
roundedRect(ctx,53,53,49,16,6);
roundedRect(ctx,53,119,49,16,6);
roundedRect(ctx,135,53,49,33,10);
roundedRect(ctx,135,119,25,49,10);
//绘制第一个吃豆人
ctx.beginPath();
ctx.arc(37,37,13,Math.PI/7,-Math.PI/7,false);
ctx.lineTo(31,17);
ctx.fill();
//绘制三排小豆子
for(var i=0; i<8; i++){
ctx.fillRect(51+i*16,35,4,4);
}
for(var i=0; i<6; i++){
ctx.fillRect(115,51+i*16,4,4);
}
for(var i=0; i<8; i++){
ctx.fillRect(51+i*16,99,4,4);
}
//绘制怪物
ctx.beginPath();
ctx.moveTo(83,116);
ctx.lineTo(83,102);
ctx.bezierCurveTo(83,94,89,88,97,88);
ctx.bezierCurveTo(105,88,111,94,111,102);
ctx.lineTo(111,116);
ctx.lineTo(106.333,111.333);
ctx.lineTo(101.666,116);
ctx.lineTo(97,111.333);
ctx.lineTo(92.333,116);
ctx.lineTo(87.666,111.333);
ctx.lineTo(83,116);
ctx.fill();
//绘制眼睛
ctx.beginPath();
ctx.fillStyle="white";
ctx.moveTo(91,96);
ctx.bezierCurveTo(88,96,87,99,87,101);
ctx.bezierCurveTo(87,103,88,106,91,106);
ctx.bezierCurveTo(94,106,95,103,95,101);
ctx.bezierCurveTo(95,99,94,96,91,96);
ctx.moveTo(103,96);
ctx.bezierCurveTo(100,96,99,99,99,101);
ctx.bezierCurveTo(99,103,100,106,103,106);
ctx.bezierCurveTo(106,106,107,103,107,101);
ctx.bezierCurveTo(107,99,106,96,103,96);
ctx.fill();
//绘制两颗眼珠
ctx.beginPath();
ctx.fillStyle="black";
ctx.arc(101,102,2,0,Math.PI*2,true);
ctx.fill();
ctx.beginPath();
ctx.arc(89,102,2,0,Math.PI*2,true);
ctx.fill();}
//绘制圆角矩形的函数
function roundedRect(ctx, x, y, width, height, radius){
ctx.beginPath();
ctx.moveTo(x, y+radius);
ctx.lineTo(x, y+height-radius);
ctx.quadraticCurveTo(x, y+height, x+radius, y+height);
ctx.lineTo(x+width-radius, y+height);
ctx.quadraticCurveTo(x+width, y+height, x+width, y+height-radius);
ctx.lineTo(x+width, y+radius);
ctx.quadraticCurveTo(x+width, y, x+width-radius, y);
ctx.lineTo(x+radius, y);
ctx.quadraticCurveTo(x, y, x, y+radius);
ctx.stroke();
}