Canvas 基本绘图方法总结
一.基本内容
1.简单来说,HTML5提供的新元素<canvas>
2.Canvas在HTML页面提供画布的功能,在画布中绘制各种图形
3.Canvas绘制的图形与HTML页面无关,无法通过DOM获取绘制的图形,无法为绘制的图形绑定DOM事件
4.只能使用Canvas提供的API
5.Canvas的用途 在HTML页面中绘制图表(例如柱状图、饼状图等);网页游戏
二、如何使用Canvas
1.在HTML页面中定义<canvas>元素
2.在JavaScript代码中
*获取<canvas>元素
*创建画布对象 如text('2d')方法
*使用Canvas提供的API
三、绘制图形
1.绘制矩形
*fillRect(x,y,width,height) - 实心矩形
* x和y - 矩形的左上角坐标
* width和height 矩形的宽度和高度
*strokeRect(x,y,width,height) - 空心矩形
*clearRect(x,y,width,height)
*清除指定区域的矩形
示例:
1 <canvas id="canvas" width="500px" height="500px"></canvas> 2 <script> 3 //绘制矩形 4 var canvas = document.getElementById("canvas"); 5 var context = canvas.getContext("2d"); 6 7 // Canvas绘制图形的默认颜色 - 黑色 8 9 // 1. 绘制实心矩形 10 context.fillRect(10,10,100,100); 11 // 2. 绘制空心矩形 - 默认边框宽度为1 12 context.strokeRect(120,10,100,100); 13 // 3. 清除指定区域的矩形 14 context.fillRect(240,10,100,100); 15 context.clearRect(250,20,80,80); 16 17 context.strokeRect(360,10,100,100); 18 //context.clearRect(359,9,102,102) 19 </script>
2.设置颜色
*fillStyle - 设置填充颜色
*strokeStyle - 设置描边颜色
*globalAlphp - 设置透明度(0-1)
示例:
1 <script> 2 // 当前绘制的矩形是什么颜色?green 3 context.fillStyle = "pink"; 4 context.fillRect(120,10,100,100); 5 // 设置描边颜色 6 context.strokeStyle = "blue"; 7 context.strokeRect(230,10,100,100); 8 // 设置透明度 9 context.fillStyle = "red"; 10 context.globalAlpha = 0.5;//透明度设置 11 context.fillRect(340,10,100,100); 12 </script>
3.设置渐变
*线性渐变 - createLinearGradient(x1,y1,x2,y2)
* 具有基准线 - 起点(x1,y1)和终点(x2,y2)
*扇形(射线)渐变 - createRadialGradient(x1,y1,r1,x2,y2,r2)
* 具有柱形(锥形) - 两个圆的面积
* 参数
* x1和y1 - 第一个圆的圆心坐标值
* r1 - 第一个圆的半径
* x2和y2 - 第二个圆的圆心坐标值
* r2 - 第二个圆的半径
示例:
1 <script> 2 //线性渐变绘制 3 var canvas = document.getElementById("canvas"); 4 var context = canvas.getContext('2d'); 5 /* 6 * 1. 设置线型渐变 7 * createLinearGradient(x1,y1,x2,y2) 8 * * x1和y1 - 基准线的起点坐标值 9 * * x2和y2 - 基准线的终点坐标值 10 * * 该方法返回渐变对象 11 */ 12 var grd = context.createLinearGradient(0,0,canvas.width,canvas.height); 13 /* 14 * 2. 通过渐变对象,设置渐变颜色 15 * addColorStop(postion,color)方法 16 * * postion - 设置渐变颜色的位置 17 * * 该值的范围为 0-1 18 * * color - 设置渐变的颜色 19 */ 20 grd.addColorStop(0,"red"); 21 grd.addColorStop(0.5,"yellow"); 22 grd.addColorStop(0.75,"green"); 23 grd.addColorStop(1,"blue"); 24 // 3. 设置填充颜色 - 渐变对象 25 context.fillStyle = grd; 26 // 4. 绘制矩形 27 context.fillRect(0,0,canvas.width,canvas.height); 28 </script>
1 <!-- 2 扇形渐变 3 --> 4 <script> 5 var canvas = document.getElementById("canvas"); 6 var context = canvas.getContext('2d'); 7 /* 8 * 1. 设置扇形渐变 9 * createRadialGradient(x1,y1,r1,x2,y2,r2) 10 * * x1和y1 - 第一个基准圆的圆心坐标值 11 * * r1 - 第一个基准圆的半径 12 * * x2和y2 - 第二个基准圆的圆心坐标值 13 * * r2 - 第二个基准圆的半径 14 * * 该方法返回渐变对象 15 */ 16 var grd = context.createRadialGradient(canvas.width/2,canvas.height/2,10,canvas.width/2,canvas.height/2,200); 17 // 2. 设置渐变颜色 18 grd.addColorStop(0,"red"); 19 grd.addColorStop(0.8,"yellow"); 20 grd.addColorStop(1,"blue"); 21 // 3. 设置填充颜色为渐变 22 context.fillStyle = grd; 23 // 4. 绘制矩形 24 context.fillRect(0,0,canvas.width,canvas.height); 25 </script>
4.绘制文字
* 方法
* fillText(text,x,y) - 实心文字
* text - 绘制的文字内容
* x和y - 绘制的坐标值
* strokeText(text,x,y) - 空心文字
* 属性
* font - 类似于CSS中的font属性
* textAlign - 设置文字的水平方向对齐
* left - 左对齐
* center - 水平居中
* right - 右对齐
* textBaseline - 设置文字的垂直方向对齐
* top - 顶部对齐
* middle - (垂直)居中对齐
* bottom - 底部对齐
* hanging - 悬挂基线
* alphabetic - 字母基线
* 注意
* 无论是水平方向还是垂直方向对齐,基准线对齐,并不是文字对齐
* 无论是水平方向还是垂直方向对齐,并不是必要的属性(不使用也是可以的)
示例:
1 <script> 2 var canvas = document.getElementById("canvas"); 3 var context = canvas.getContext("2d"); 4 5 // 绘制文字的基准线 6 context.beginPath(); 7 context.moveTo(100,0); 8 context.lineTo(100,200); 9 context.stroke(); 10 11 // 1. 设置文字的相关信息 12 context.font = "bold 48px 宋体"; 13 14 context.fillText("你好",300,200); 15 16 context.textAlign = "left"; 17 // 2. 绘制文字 18 context.fillText("达内",100,50); 19 20 context.textAlign = "center"; 21 context.fillText("达内",100,100); 22 23 context.textAlign = "right"; 24 context.fillText("达内",100,150); 25 26 // 绘制基准线 27 context.beginPath(); 28 context.moveTo(0,300); 29 context.lineTo(500,300); 30 context.stroke(); 31 32 // 绘制空心文字 33 context.textBaseline= "top"; 34 context.strokeText("达内",100,300); 35 </script>
5.绘制阴影
* 阴影效果
* shadowColor - 设置阴影颜色
* shadowOffsetX - 设置水平方向阴影
* shadowOffsetY - 设置垂直方向阴影
* shadowBlur - 设置阴影的模糊程度
示例:
1 <script> 2 var canvas = document.getElementById("canvas"); 3 var context = canvas.getContext("2d"); 4 5 // 设置阴影效果 6 context.shadowColor = "red"; 7 context.shadowOffsetX = 0; 8 context.shadowOffsetY = 0; 9 context.shadowBlur = 10; 10 11 // 绘制文字 12 context.font = "bold 48px 微软雅黑"; 13 context.fillText("达内",200,200); 14 15 context.fillRect(10,10,100,100); 16 context.strokeRect(120,10,100,100); 17 </script>
6.创建路径
* (标识)方法
* beginPath() - 表示开始创建路径
* closePath() - 表示结束创建路径
* 设置方法
* rect(x,y,width,height) - 设置矩形形状
* x和y - 设置矩形的左上角坐标值
* width和height - 设置矩形的宽度和高度
* arc(x,y,radius,startAngle,endAngle,direction) - 设置圆形形状
* x和y - 设置圆形的圆心坐标值
* radius - 设置圆形的半径
* startAngle和endAngle - 设置圆形的起始位置
* direction - 按照顺时针或逆时针绘制
* 绘制方法
* stroke() - 绘制轮廓
* fill() - 绘制填充
示例:
1 <script> 2 var canvas = document.getElementById("canvas"); 3 var context = canvas.getContext("2d"); 4 5 // 1. 调用beginPath()方法(必要),表示开始创建路径 6 context.beginPath(); 7 // 2. 设置形状 - 矩形 8 context.rect(10,10,100,100); 9 // 3. 调用closePath()方法(可写可不写) 10 context.closePath(); 11 // 4. 绘制 12 context.fill(); 13 14 // 利用创建路径绘制空心矩形 15 // 问题:是否需要再次调用beginPath()?编写 16 context.beginPath();//不写,上一个图形变虚 17 context.rect(10,120,100,100); 18 context.stroke(); 19 20 // 使用创建路径绘制实心圆形 21 context.beginPath(); 22 /* 23 * arc(x,y,radius,startAngle,endAngle,direction); 24 * * x和y1 - 设置圆形的圆心坐标值 25 * * radius - 设置圆形的半径 26 * * startAngle和endAngle 27 * * direction - 是顺时针还是逆时针 28 * * Boolean值,默认值为false,表示顺时针 29 */ 30 context.arc(170,60,50,0,Math.PI*2); 31 context.fill(); 32 33 </script>
7.绘制线条
* lineWidth - 设置线条的宽度
* 默认值为1(px)
* lineCap - 设置线条端点的形状
* butt - 默认值,平直
* round - 圆角
* square - 正方向
* lineJoin - 设置两条线焦点的形状
* miter - 默认值,尖角
* round - 圆角
* bevel - 斜角
* miterLimit - 配合lineJoin使用
* lineJoin设置为miter,该属性值设置尖角的延伸范围
示例:
1 <script> 2 //绘制线条 3 var canvas = document.getElementById("canvas"); 4 var context = canvas.getContext("2d"); 5 6 // 1. 表示开始创建路径 7 context.beginPath(); 8 // 2. 设置直线(折线)的起点坐标值 9 context.moveTo(10,10); 10 // 3. 设置直线(折线)的终点(折点)坐标值 11 context.lineTo(100,10); 12 context.lineTo(100,100); 13 context.lineTo(10,100); 14 context.lineTo(10,10); 15 // 4. 绘制 - stroke() 16 context.stroke(); 17 18 context.beginPath(); 19 context.moveTo(200,100); 20 context.lineTo(400,100); 21 context.lineTo(400,400); 22 context.lineTo(200,400); 23 context.lineTo(300,300); 24 context.lineTo(200,100); 25 context.stroke(); 26 27 //设置线条属性 28 // 设置线条 29 context.lineWidth = 10; 30 context.lineCap = "round";//设置端点处 31 context.lineJoin = "round";//设置相交处 32 context.miterLimit = 15; 33 34 // 绘制一条折线 35 context.beginPath(); 36 context.moveTo(10,10); 37 context.lineTo(300,300); 38 context.lineTo(100,50); 39 context.stroke(); 40 // 绘制空心矩形 41 context.strokeRect(350,200,100,100); 42 </script>
四、Canvas处理图片
1.绘制图片
* drawImage(img,x,y) - 按照图片原大小加载
* img - 当前加载(绘制)的图片
* x和y - 绘制图片的坐标值(左上角)
* drawImage(img,x,y,width,height) - 按照指定大小加载图片
* img - 当前加载(绘制)的图片
* x和y - 绘制图片的坐标值(左上角)
* width和height - 设置绘制图片显示的宽度和高度
* 注意
* 必须保证图片加载完毕(onload事件)后,再绘制图片
示例:
1 <canvas id="canvas" width="900px" height="600px" style="background:pink"></canvas> 2 <script> 3 var canvas = document.getElementById("canvas"); 4 var context = canvas.getContext("2d"); 5 6 // 1. 加载一张图片 7 var myimg = new Image(); 8 myimg.src = "Tulips.jpg"; 9 /* 10 * 2. 绘制加载的图片 11 * 问题 - 图片并没有出现Canvas画布中 12 * * 原因 13 * * HTML页面加载<canvas>元素 - 画布 14 * * HTML页面加载图片 15 * * 使用drawImage()绘制图片 16 * * 加载<canvas>与图片、drawImage()之间没有必然联系 17 * * 要求 18 * * 必须先加载<canvas>元素,再加载图片 19 * * (出问题)必须先加载完毕图片,再执行绘制图片 20 * * 解决 21 * * 图片的onload事件 - 保证图片加载完毕 22 */ 23 myimg.onload = function(){ 24 context.drawImage(myimg,10,10,512,384); 25 } 26 </script> 27
2.平铺图片
* createPattern(img,type)
* img - 平铺的图片
* type - 平铺的方式
* repeat - 平铺
* no-repeat - 不平铺
* repeat-x - 水平方向平铺
* repeat-y - 垂直方向平铺
示例:
1 <canvas id="canvas" width="900px" height="600px"></canvas> 2 <script> 3 var canvas = document.getElementById("canvas"); 4 var context = canvas.getContext("2d"); 5 6 // 1. 加载图片 7 var myimg = new Image(); 8 myimg.src = "house.jpg"; 9 myimg.onload = function(){ 10 // 2. 设置平铺 11 var ptn = context.createPattern(myimg,"repeat"); 12 // 3. 设置颜色为图片平铺 13 context.fillStyle = ptn; 14 // 4. 绘制矩形 15 context.fillRect(0,0,canvas.width,canvas.height); 16 } 17 </script>
3.切割图片
* clip() - 切割(按照创建路径使用)
示例:
1 <canvas id="canvas" width="512px" height="500px"></canvas> 2 <script> 3 var canvas = document.getElementById("canvas"); 4 var context = canvas.getContext("2d"); 5 // 绘制图片 6 var myimg = new Image(); 7 myimg.src = "Tulips.jpg"; 8 myimg.onload = function(){ 9 context.drawImage(myimg,0,0,512,384); 10 } 11 // 切割图片 12 context.beginPath(); 13 context.arc(240,100,80,0,Math.PI*2); 14 context.clip(); 15 </script>
五、Canvas画布方法
1. scale(x,y) - 缩放(缩小与放大)
* x - 表示水平方向的缩放
* y - 表示垂直方向的缩放
* 参数取值
* 如果为1的话,表示不缩放(原大小)
* 如果小于1的话,表示缩小
* 如果大于1的话,表示放大
2. translate(x,y) - 重新定位(x,y)
* x,y - 新的坐标值
* 任意 - x,y是相对于上次定位坐标值
3. rotate(旋转角度) - 旋转画布
* 公式为 degrees * Math.PI / 180 ;
示例:
1 <canvas id="canvas" width="500px" height="500px"></canvas> 2 <script> 3 var canvas = document.getElementById("canvas"); 4 var context = canvas.getContext("2d"); 5 6 // 1. 重新定位 7 context.translate(200,100); 8 // 2. 缩放 0.5 9 context.scale(0.5,0.5); 10 // 3. 旋转 11 context.rotate(Math.PI/10); 12 13 // 绘制实心矩形 14 context.fillStyle = "pink"; 15 context.fillRect(0,0,100,50); 16 </script>
六、一些练习的小例子
1. rotato螺旋图
1 <canvas id="canvas" width="300px" height="300px" style="border:solid 1px black"></canvas> 2 <input id="start" type="button" value="开始"> 3 <script> 4 var canvas = document.getElementById("canvas"); 5 var context = canvas.getContext("2d"); 6 7 var btn = document.getElementById("start"); 8 btn.onclick = function(){ 9 // 完成螺旋图 10 context.translate(150,50); 11 context.scale(0.95,0.95); 12 13 context.fillStyle = "blue"; 14 context.globalAlpha = 0.5; 15 context.fillRect(0,0,100,50); 16 17 for(var i=0;i<50;i++){ 18 // 相对上次定位坐标值 19 context.translate(20,20); 20 context.scale(0.95,0.95); 21 context.rotate(Math.PI/15); 22 23 context.fillRect(0,0,100,50); 24 } 25 } 26 </script>
2.小球随鼠标移动
这个示例需要注意的只有两点 1.获取鼠标的移动的坐标 2.圆形的重绘及画布清除问题
1 <body> 2 <canvas id="canvas" width="900px" height="500px" style="border:1px solid #000"></canvas> 3 </body> 4 <script> 5 var canvas = document.getElementById("canvas"); 6 var context = canvas.getContext("2d"); 7 8 context.beginPath(); 9 context.fillStyle = "#f50000"; 10 context.arc(100,100,30,0,Math.PI*2); 11 context.fill(); 12 13 canvas.onmousemove = function(event){ 14 var x = event.offsetX; 15 var y = event.offsetY; 16 console.log(x+" "+y); 17 18 //重绘 19 context.clearRect(0,0,900,500);//清除画布 20 context.beginPath(); 21 context.arc(x,y,30,0,Math.PI*2); 22 context.fill(); 23 } 24 </script>
3.多球掉落
我写着的这个例子会比上边的稍微难一点,我的思路是这样的:
1.先建立一个构造器,保存小球的 x,y坐标 r半径 颜色 透明度等信息
//小球构造函数 function sphere(x,y,r,color,alpha){ this.x = x;//小球x坐标 this.y = y;//小球y坐标 this.r = r;//小球r半径 this.color = color;//小球颜色 this.alpha = alpha;//透明度 }
2.设置一些基本的数据参数 小球用一个数组存储
//canvas画布的宽度和高度 var WIDTH = canvas.width; var HEIGHT = canvas.height; //小球出现的频率 var SPHERETIME = 500; //整体重绘时间间隔 var REDAWTIME = 10; //初始化x,y坐标 color颜色 var x=50,y=50,color="#000",alpha="1"; //小球存储数组 var spheres = [];
3.用一个定时器来生成小球并存放到数组中
setInterval(function(){ //随机半径 var r = parseInt(Math.random()*31+10);//10~30 半径 //随机x坐标 x = parseInt(Math.random()*WIDTH); x>WIDTH-r&&(x = WIDTH-r);//判断球右侧超出 x<r&&(x=r);//判断球左侧超出 //随机颜色 color = "rgb("+parseInt(Math.random()*255)+","+parseInt(Math.random()*255)+","+parseInt(Math.random()*255)+")"; //透明度随机 alpha = Math.random().toFixed(1); spheres.push(new sphere(x,-r,r,color,alpha)); },SPHERETIME);
4.最后一步吧数组中的小球绘制到Canvas画布中
//整体重绘 function drawCircles(){ //关于背景这里有两个方法 1,在画布中设置一个图片背景每次都重置;2,在vanvas的标签中设置背景图片,用clearRect的方法清空画布 都可以达到效果,在这里第二种更加的方便 //图片重绘 context.drawImage(myimg,0,0); //context.clearRect(0,0,900,500); for (var i=0; i<spheres.length; i++) { if (spheres[i].y>HEIGHT) { //删除当前超出画布的小球对象 spheres.splice(i,1); i--;//每当删除一个数组元素,就要重新判断当前元素 continue; } // 绘制圆形 context.beginPath(); context.fillStyle=spheres[i].color; //透明度设置 context.globalAlpha = spheres[i].alpha;//这里设置透明度会有一些画面延迟问题,使用rgba设置透明度就没有问题 context.arc(spheres[i].x,spheres[i].y+=1,spheres[i].r,0,Math.PI*2);//绘制圆型 context.fill();//实心绘制 } setTimeout(drawCircles,REDAWTIME);//小球整体重绘间隔我觉得用setTimeout比较好 }
6.写完后的一些想法,有提议把小球的透明度的效果改为 随着小球的掉落不透明度逐渐降低 让小球调到底部透明消失;
还有一个重要的问题(很高心您看到了这里,如果您知道下面问题的答案或更好的方法,请留言,感谢不尽):在设置小球不透明度的时候(context.globalAlpha = spheres[i].alpha;)由于频繁调用这个函数,在画面绘制的时候会造成延时,小球闪烁,画面滞带的问题;个人理解:globalAlpha这个函数可以当成全局使用,就是在大批量绘制同一透明度图像时比较有用,但是在这种频繁调用的时候就会影响性能,我找的解决方法就是给小球的颜色格式设置为rgba这样可以解决。如果有大神看到了这里,希望您能指点一下canvas绘图中的函数的性能问题,或者使用canvas做游戏绘制图象时,怎么解决外部图形频繁加载的问题,比如将图像直接写入内存并在内存中操作等的方法提要图像效率的方案。
7.附上小球掉落的所有代码
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>小球掉落</title> 5 <meta charset="utf-8"> 6 </head> 7 8 <body> 9 <canvas id="canvas" width="900px" height="500px" style="background-color:#fff;border:1px solid #000;background-image:url('bg.jpg')"></canvas> 10 </body> 11 <script> 12 var canvas = document.getElementById("canvas"); 13 var context = canvas.getContext("2d"); 14 // 绘制图片 - 当前画布的背景图片 15 var myimg = new Image(); 16 myimg.src = "bg.jpg"; 17 //canvas画布的宽度和高度 18 var WIDTH = canvas.width; 19 var HEIGHT = canvas.height; 20 //小球出现的频率 21 var SPHERETIME = 500; 22 //整体重绘时间间隔 23 var REDAWTIME = 10; 24 25 //初始化x,y坐标 color颜色 26 var x=50,y=50,color="#000",alpha="1"; 27 //小球存储数组 28 var spheres = []; 29 //小球构造函数 30 function sphere(x,y,r,color,alpha){ 31 this.x = x;//小球x坐标 32 this.y = y;//小球y坐标 33 this.r = r;//小球r半径 34 this.color = color;//小球颜色 35 this.alpha = alpha;//透明度 36 } 37 38 //整体重绘 39 function drawCircles(){ 40 //console.log(spheres.length); 41 //图片重绘 42 context.drawImage(myimg,0,0); 43 //context.clearRect(0,0,900,500); 44 for (var i=0; i<spheres.length; i++) 45 { 46 if (spheres[i].y>HEIGHT) 47 { 48 //删除当前超出画布的小球对象 49 spheres.splice(i,1); 50 i--; 51 continue; 52 } 53 // 绘制圆形 54 context.beginPath(); 55 context.fillStyle=spheres[i].color; 56 //透明度设置 57 context.globalAlpha = spheres[i].alpha; 58 //context.globalAlpha > 0.5 ? (context.globalAlpha = 0.2) : (context.globalAlpha = 0.8); 59 60 context.arc(spheres[i].x,spheres[i].y+=1,spheres[i].r,0,Math.PI*2);//绘制圆型 61 context.fill();//实心绘制 62 } 63 setTimeout(drawCircles,REDAWTIME);// 64 } 65 66 //小球随机出现 67 setInterval(function(){ 68 //随机半径 69 var r = parseInt(Math.random()*31+10);//10~30 半径 70 //随机x坐标 71 x = parseInt(Math.random()*WIDTH); 72 x>WIDTH-r&&(x = WIDTH-r);//判断球右侧超出 73 x<r&&(x=r);//判断球左侧超出 74 //随机颜色 75 color = "rgb("+parseInt(Math.random()*255)+","+parseInt(Math.random()*255)+","+parseInt(Math.random()*255)+")"; 76 //透明度随机 77 alpha = Math.random().toFixed(1); 78 spheres.push(new sphere(x,-r,r,color,alpha)); 79 80 },SPHERETIME); 81 82 drawCircles();//调用整体绘制函数 83 84 </script> 85 </html>