【上篇】 -- 建议学习时间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颜色/透明度

关注公众号,博客更新即可收到推送

最新文章

  1. 无废话Android之android下junit测试框架配置、保存文件到手机内存、android下文件访问的权限、保存文件到SD卡、获取SD卡大小、使用SharedPreferences进行数据存储、使用Pull解析器操作XML文件、android下操作sqlite数据库和事务(2)
  2. TODO:Half Half的设计
  3. 解析八大O2O典范:他们都做了什么?
  4. OpenJudge计算概论-循环移动
  5. 浏览器后退按钮导致jquery动态添加的select option值丢失的解决方法
  6. (转载)file_get_contents(&quot;php://input&quot;)
  7. FUSE
  8. apache通过AD验证
  9. D&#160;区间求和 [数学 树状数组]
  10. vue使用过滤器利用moment实现日期的格式化
  11. php的phar是什么?
  12. DLG消息
  13. SignalR 行实时通信遇到的
  14. 05 Django REST Framework 分页
  15. jQuery preventDefault() ,stopPropagation(),stopImmediatePropagation()
  16. playbook
  17. System.map文件的作用解析
  18. .Net调用QQ邮箱发送邮件
  19. linux刻录iso到u盘
  20. Linux内核分析实验五

热门文章

  1. 【二分图】【并查集】XVII Open Cup named after E.V. Pankratiev Stage 14, Grand Prix of Tatarstan, Sunday, April 2, 2017 Problem L. Canonical duel
  2. bzoj 1787: [Ahoi2008]Meet 紧急集合
  3. uva1632 (区间DP)
  4. 【Data URL】【RE】【bugku】逆向入门writeup
  5. 【常见加密方法】Base64编码&amp;Tea算法简介
  6. C++ cout输出保留小数
  7. 【Tomcat MyEcplise】MyEcplise添加一个新的Server,Tomcat8.5报错
  8. Lua学习之类型与值
  9. pytho文件命名不要内部模块或者引用模块名字相同
  10. [转]在SSIS中,使用“包配置”时的常见错误与解析