【上篇】 -- 建议学习时间4小时 课程共(上中下)三篇
此笔记是我初次接触canvas的时候的学习笔记,这次特意整理为博客供大家入门学习,几乎涵盖了canvas所有的基础知识,并且有众多练习案例,建议大家学习10~15个小时,里面的案例请挨个敲一遍,这样才能转化为自己的知识。
技术要求:有html/css/js基础。
canvas标签
<canvas>是一个图形容器,让我们在网页中绘制图形,很多人把它称为画布,使用canvas绘制图形就相当于在画布上画画一样,我们可以绘制非常炫酷的页面效果。
如下图这种:
上面的效果当然要后期才有能力编写了,现在我们先从简单的入手
直接看代码
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <style> *{margin: 0;padding: 0} canvas{border: 2px solid #a4e2f9;margin: 30px auto;display: block} </style> </head> <body> <canvas height="300" width="500" id="myCanvas"></canvas> </body> </html>
我们定义了一个canvas标签(用法和普通标签一样),然后在style中设置了一点样式。
注意:canvas的真实宽高一定要在canvas属性中设置,不能在css中设置,因为canvas默认的宽高是 300*150,如果在css中设置样式,相当于是把画布进行拉伸缩放
呈现效果是这样的:
对于不支持画布的浏览器,我们可以在中间设置替代显示内容
<canvas id="myCanvas" width="150" height="150"> 你的浏览器不支持画布 </canvas>
在画布中绘制方块
代码写到html末尾的<script>标签中
var c = document.getElementById("myCanvas"); var ctx = c.getContext("2d"); ctx.fillStyle = "red"; //设置颜色 ctx.fillRect(50,50, 200, 200); //绘制方块
代码解释:首先要获取canvas的dom,并获取它的2d上下文,然后才能绘制,绘制使用fillRect(x, y, width, height)绘制方块填充,使用fillStyle设置填充的颜色
注:我们所有对画布的操作,都需要先去获取绘图上下文才能操作,也就是 getContext("2d")
然后绘制方块描边,使用strokeRect(x, y, width, height),使用strokeStyle设置描边颜色
var c = document.getElementById("myCanvas"); var ctx = c.getContext("2d"); //ctx.fillStyle = "red"; //设置颜色 //ctx.fillRect(50,50, 200, 200); //绘制方块 ctx.strokeStyle = "red"; ctx.strokeRect(50,50, 200, 200); //绘制边框
如果要清除(擦除)某个区域,使用 clearRect(x, y, width, height),
如下,我们绘制了方块,并且清除了绘制的区域,这样就什么都看不到了。
var c = document.getElementById("myCanvas"); var ctx = c.getContext("2d"); ctx.fillStyle = "red"; //设置颜色 ctx.fillRect(50,50, 200, 200); //绘制方块 ctx.clearRect(50,50, 200, 200); //清除范围
注意:这里清除的是方块,如果要清除方块描边的话,需要把范围扩大(因为描边默认是外描边) ctx.clearRect(48,48, 204, 204); //清除范围
绘制路径
使用beginPath()表示开始绘画,使用 moveTo(x,y)标记绘制起点,使用 lineTo()进行绘制 ,使用closePath()闭合路径,绘制完成路径之后在使用 stroke()来绘制轮廓
var c = document.getElementById("myCanvas"); var ctx = c.getContext("2d"); //绘制路径 ctx.beginPath(); ctx.moveTo(100, 100); //通常会使用moveTo()函数设置起点。我们也能够使用moveTo()绘制一些不连续的路径。 ctx.lineTo(200,100); ctx.lineTo(200,200); ctx.moveTo(300, 100); ctx.lineTo(300, 200); ctx.lineTo(400, 200); ctx.closePath();// 闭合路径,会自动闭合路径开始和结束的两个点 ctx.stroke(); //绘制轮廓
显示结果如下:
如果要绘制填充,使用 fill()
var c = document.getElementById("myCanvas"); var ctx = c.getContext("2d"); //绘制路径 ctx.beginPath(); ctx.moveTo(100, 100); //通常会使用moveTo()函数设置起点。我们也能够使用moveTo()绘制一些不连续的路径。 ctx.lineTo(200,100); ctx.lineTo(200,200); ctx.moveTo(300, 100); ctx.lineTo(300, 200); ctx.lineTo(400, 200); ctx.closePath();// 闭合路径,会自动闭合路径开始和结束的两个点 ctx.fill(); //绘制块 (会自动闭合路径)
绘制填充会自动闭合路径,可以不用使用 closePath()
绘制圆形
使用arc(),具体参数如下
arc(x, y, radius, startAngle, endAngle, anticlockwise)
该方法有六个参数:x,y为绘制圆弧所在圆上的圆心坐标。radius为半径。startAngle以及endAngle参数用弧度定义了开始以及结束的弧度。这些都是以x轴为基准。参数anticlockwise 为一个布尔值。为true时,是逆时针方向,否则顺时针方向。
绘制一个圆圈:
var c = document.getElementById("myCanvas"); var ctx = c.getContext("2d"); ctx.arc(100, 100, 50, 0, Math.PI*2, true);// 绘制圆圈轨迹 ctx.stroke();
练习:绘制笑脸
var c = document.getElementById("myCanvas"); var ctx = c.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();
练习:绘制两个三角形
var c = document.getElementById("myCanvas"); var ctx = c.getContext("2d"); //绘制两个三角形 ctx.beginPath(); ctx.moveTo(50, 50); ctx.lineTo(150, 50); ctx.lineTo(50, 150); ctx.fill(); ctx.beginPath(); ctx.moveTo(170, 70); ctx.lineTo(170, 170); ctx.lineTo(70, 170); ctx.closePath(); ctx.stroke();
绘制曲线
使用 贝塞尔函数
quadraticCurveTo(cp1x, cp1y, x, y)
绘制贝塞尔曲线,cp1x,cp1y为控制点,x,y为结束点。
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
绘制二次贝塞尔曲线,cp1x,cp1y为控制点一,cp2x,cp2y为控制点二,x,y为结束点。
绘制上上图曲线的代码如下:
var c = document.getElementById("myCanvas"); var ctx = c.getContext("2d"); ctx.beginPath(); ctx.moveTo(100,100); ctx.quadraticCurveTo(150,50,200,100); ctx.quadraticCurveTo(250,150,300,100); ctx.quadraticCurveTo(350,50,400,100); ctx.stroke();
练习:绘制聊天气泡
var c = document.getElementById("myCanvas"); var ctx = c.getContext("2d"); //绘制聊天小气泡 ctx.beginPath(); ctx.moveTo(100,130); ctx.quadraticCurveTo(100,100,130,100); ctx.lineTo(270,100); ctx.quadraticCurveTo(300,100,300,130); ctx.lineTo(300,200); ctx.quadraticCurveTo(300,230,270,230); ctx.lineTo(175,230); ctx.quadraticCurveTo(140,280,100,280); ctx.quadraticCurveTo(130,280,150,230); ctx.lineTo(130,230); ctx.quadraticCurveTo(100,230,100,200); ctx.closePath(); ctx.stroke();
练习:绘制心形
var c = document.getElementById("myCanvas"); var ctx = c.getContext("2d"); //绘制心形 ctx.beginPath(); ctx.moveTo(100,130); ctx.bezierCurveTo(100,50,170,50,200,100); ctx.bezierCurveTo(230,50,300,50,300,130); ctx.bezierCurveTo(300,140,300,210,200,250); ctx.bezierCurveTo(100,200,100,140,100,130); ctx.stroke();
综合练习:绘制吃豆子
var c = document.getElementById("myCanvas"); var ctx = c.getContext("2d"); //绘制吃豆子 roundedRect(ctx,12,12,195,174,15); roundedRect(ctx,19,19,180,160,9); roundedRect(ctx,53,53,49,33,10); 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,37); 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.fillStyle = "white"; ctx.beginPath(); 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.fillStyle = "red"; ctx.beginPath(); ctx.arc(101,102,2,0,Math.PI*2,true); ctx.arc(89,102,2,0,Math.PI*2,true); ctx.fill(); //绘制圆角矩形的方法 function roundedRect(ctx,x,y,width,height,radius){ ctx.moveTo(x,x+radius); ctx.beginPath(); 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.closePath(); ctx.stroke(); }
附加知识: 注:附加知识属于提高或者不重要的知识,可以像思考题一样对待
Path2d()
Path2D()会返回一个新初始化的Path2D对象(可能将某一个路径作为变量——创建一个它的副本,或者将一个包含SVG path数据的字符串作为变量)。
var c = document.getElementById("myCanvas"); var ctx = c.getContext("2d"); //Path2D 示例 var rectangle = new Path2D(); rectangle.rect(10,10,50,50); var circle = new Path2D(); circle.moveTo(125,35); circle.arc(100,35,25,0,2*Math.PI); ctx.stroke(rectangle); ctx.fill(circle);
今天就讲到这里,下节课我们讲解:canvas颜色/透明度
关注公众号,博客更新即可收到推送