(1)canvas是什么?
我们翻译一下这个单词,会发现它有「 画布 」的意思。
画布画布不就是绘制图形的么?不过不同的是canvas元素是在网页上绘制图形!
其实canvas 元素就是使用 JavaScript 在网页上绘制图像。而绘制的画布区域是一个矩形区域,我们可以控制其中每一像素,以达到想画啥就画啥的效果。canvas 拥有多种绘制路径、矩形、圆形、字符以及添加图像的方法。
(2)如何使用?
上面说canvas 元素就是使用 JavaScript 在网页上绘制图像!所以关于canvas的使用也分为两步:
第一步:在HTML5页面创建canvas元素;
第二步:通过JavaScript来绘制。
1️⃣创建 Canvas 元素:
向 HTML5 页面添加 canvas 元素!
规定此canvas元素的 id、宽度和高度(宽度和高度即指定画布的大小!):
<!--canvas默认大小:宽300px,高150px-->
<canvas id="myCanvas" width="200" height="100"></canvas>
2️⃣通过 JavaScript 来绘制:
canvas 元素本身是没有绘图能力的。所有的绘制工作必须在 JavaScript 内完成:
<script type="text/javascript">
//第一步,匹配到canvas对象。
var c=document.getElementById("myCanvas");
//第二步,获取canvas的上下文环境
var cxt=c.getContext("2d"); //getContext("2d") 对象是内建的 HTML5 对象,拥有多种绘制路径、矩形、圆形、字符以及添加图像的方法。
// 绘制一个红色的矩形:
cxt.fillStyle="red";
// fillRect方法是绘制矩形 参数:绘制矩形的左上角x坐标,y坐标,x方向长度,y方向长度
cxt.fillRect(0,0,150,75); // 在画布上绘制 150x75 的矩形,从左上角开始 (0,0)。
</script>
3️⃣实现效果
需要注意的是:canvas的画布区域,左上角为坐标原点(0,0),分别向右为x轴,向下为y轴。

2.中级阶段——绘制一些常见的基本图形~
-
要知道,再复杂的图形也都是由各种基本图形组合而成。
-
所以,先来看看如何绘制各种常见的基本图形。
-
这样,进行一些需要使用canvas的项目设计时才会手到擒来!
🚓(1)绘制一条直线
-
指定起始(x,y)坐标;
-
指定粗细;
-
指定颜色。
注意:通过CSS定位到canvas元素,并为其设置一个显眼的border样式,方便下面观察!
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
/*设置canvas画布样式——画布边框粗细1px;实线;红色*/
#myCanvas{
border: 1px solid red;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="300" height="250"></canvas>
</body>
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
// 1.首先,将画笔定位到起点坐标处;
ctx.moveTo(50,50);
// 2.然后,从当前位置连一条线到终点坐标处(注意:此时并没有真正的画线!)
ctx.lineTo(100,50);
ctx.strokeStyle = "blue"; // 线条的颜色
ctx.lineWidth = "5"; // 线条的粗细
// 3.最后,画线条,作用是描边————这句才是真正的画线!
ctx.stroke(); // 认真学习的同学可以将本行注释再看看效果哦!
</script>
</html>
实现效果:

🚑(2)绘制一条折线
-
指定折点处的形状;
-
指定线端点的形状。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
#myCanvas{
border: 1px solid red;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="300" height="250"></canvas>
</body>
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
// 1.首先,将画笔定位到起点坐标处
ctx.moveTo(50,50);
// 2.然后,从当前位置连一条线到重点坐标处【因为现在画的是折线,所以拐两拐】(注意:并不是真画线!)
ctx.lineTo(100,50);
ctx.lineTo(60,80);
// 3.指定线段端点形状 ———— round:圆形;square:正方形;butt:默认
ctx.lineCap = "round";
// 4.指定线交点(折线点)的形状 ———— round:圆形;miter:默认;bevel:截取一部分;
ctx.lineJoin = "round";
ctx.strokeStyle = "blue"; // 线条的颜色
ctx.lineWidth = "5"; // 线条的粗细
// 5.最后,画线条,作用是描边————这句才是真正的画线!
ctx.stroke();
</script>
</html>
认真学习的小伙伴们可以尝试将lineCap和lineJoin的值多次更改,看看各种值的真实实现效果哦!
实现效果:

🚔(3)画矩形和圆
分别尝试画实心和空心!
同一张画图上绘制多个图形小知识点:
-
在同一个canvas上,即同一张画布上画图时,画笔的位置为画笔画完上一个图的结束点!
-
问题就是重新定位画笔过于麻烦!
-
解决方法——所以在一个图画完后使用.stroke()方法绘制出此图;
-
并使用方法.beginPath()新开辟一次画图,重新定位画笔即可!
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>画方,画圆</title>
<style type="text/css">
#c1{
border:1px solid blue;
}
</style>
</head>
<body>
<canvas id="c1" width="1300" height="700"></canvas>
</body>
<script type="text/javascript">
var c = document.getElementById("c1");
var ctx = c.getContext("2d");
//1.绘制空心矩形
ctx.strokeStyle = "blue";
ctx.lineWidth = 5; //线条粗细
ctx.strokeRect(50,50,250,250); //参数:左上角x,y坐标,x,y方向长度
//2.绘制实心矩形
ctx.fillStyle = "#DFFF4A"; // 指定填充颜色
ctx.fillRect(350,50,100,100);
//3.画一个既描边又填充的矩形
//第一种方法:先画一个空心矩形,然后在其内部画一个实心矩形
ctx.lineWidth = 20;
ctx.strokeRect(500,50,100,100);
ctx.fillRect(500,50,100,100);
//第二种方法:.rect()方法先画一个空心矩形,然后.fill()填充
ctx.rect(650,50,100,100);
ctx.stroke();
ctx.fill()
//4.绘制填充的圆
ctx.beginPath();
ctx.lineWidth = 3;
//参数:150,500是圆心,80是半径,0是弧的起始角度, Math.PI/2是弧的结束角度, true是逆时针;false是顺时针。
ctx.arc(150,500,80,0,Math.PI*2,true);
ctx.stroke();
ctx.fill(); // 注意:使用的填充样式都是上面设置过的!
// 5.绘制空心的圆
ctx.beginPath();
ctx.lineWidth = 3;
ctx.arc(400,500,80,0,Math.PI*2,true);
ctx.stroke();
</script>
</html>
实现效果:

🚐(4)颜色渐变之线性渐变和发散渐变
渐变可以填充在矩形, 圆形, 线条, 文本等各种形状中,主要作用是:可以自己定义不同的颜色。
当我们使用渐变对象,必须使用两种或两种以上的停止颜色。addColorStop()方法指定颜色停止,参数使用坐标来描述,可以是0至1。使用渐变,设置fillStyle或strokeStyle的值为渐变,然后绘制形状,如矩形,文本,或一条线。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>线性渐变和发散渐变</title>
<style type="text/css">
#c1{
border: 3px solid red;
}
</style>
</head>
<body>
<canvas id="c1" width="1000" height="700"></canvas>
</body>
<script type="text/javascript">
//第一步,找到canvas对象。
var c = document.getElementById("c1");
//第二步,获取canvas的上下文环境
var ctx = c.getContext("2d");
//然后就可以通过ctx进行绘制了
ctx.beginPath();
// 线性渐变的实现
//第一种: 竖着渐变,从指定的左上角坐标到右上角坐标竖着范围内进行颜色渐变
var jianbian = ctx.createLinearGradient(100,100,300,100); // 左上角x,y坐标,右上角x,y坐标
jianbian.addColorStop(0,"red");
jianbian.addColorStop(0.5,"blue");
jianbian.addColorStop(1,"yellow");
ctx.strokeStyle = jianbian;
ctx.lineWidth = 10;
ctx.moveTo(100,100);
ctx.lineTo(300,100);
ctx.stroke();
//第二种: 斜着渐变,从指定的左上角坐标到右下角坐标斜着范围内进行颜色渐变
ctx.beginPath();
var jianbian2 = ctx.createLinearGradient(400,300,600,500);
jianbian2.addColorStop(0,"cyan");
jianbian2.addColorStop(0.3,"green");
jianbian2.addColorStop(0.7,"purple");
jianbian2.addColorStop(1,"blue");
ctx.fillStyle = jianbian2;
ctx.moveTo(400,300);
ctx.lineTo(600,300);
ctx.lineTo(600,500);
ctx.lineTo(400,500);
ctx.closePath(); //使用.closePath()方法即可自动封闭图形,封闭终点坐标到起点坐标!
ctx.stroke();
ctx.fill();
// 发散渐变的实现
//指定两个圆所形成的圆环内发散向四周渐变
ctx.beginPath();
var jianbian3 = ctx.createRadialGradient(150,400,50,150,400,200); // 参数:第一个圆的圆心+半径,第二个圆的圆心+半径
jianbian3.addColorStop(0,"red");
jianbian3.addColorStop(0.3,"blue");
jianbian3.addColorStop(0.7,"yellow");
jianbian3.addColorStop(1,"green");
ctx.fillStyle = jianbian3;
ctx.moveTo(10,300);
ctx.lineTo(310,300);
ctx.lineTo(310,500);
ctx.lineTo(10,500);
ctx.closePath();
ctx.stroke();
ctx.fill();
</script>
</html>
实现效果:

🚉拓展——几种复杂图形的绘制
-
题目就是下面所列的五个,请小伙伴们发挥你们的小脑袋瓜,自己先动手绘制哦🙄!
-
所用的操作在上面都已详细讲解,没有一道题超纲哦(实践是检验真理的唯一标准🤩)
-
做完的小伙伴们可以看看下面我的代码和实现的效果,说不定你们做的比我的还要好😂!
-
使用红色填充的五角星;
-
使用渐变色填充的六边形;
-
机器人头部(使用线性渐变&&发散渐变);
-
空心的五角星;
-
绘制一个四肢健全的小人。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>自己动手,丰衣足食~</title>
<style type="text/css">
#canvas_first{
border: 5px solid red;
}
</style>
</head>
<body>
<canvas id="canvas_first" width="1500" height="700"></canvas>
</body>
<script type="text/javascript">
// 想要在canvas上画东西,第一步要先找到canvas控件
var c = document.getElementById("canvas_first");
//获取绘制的上下文环境,简单理解为画笔(实际上不是画笔)
var ctx = c.getContext("2d"); //此对象是内建的 HTML5 对象,拥有多种绘制路径、矩形、圆形、字符以及添加图像的方法。
// 1.五角星
ctx.moveTo(100,0); // 将画笔移动到指定的位置
ctx.fillStyle = "red"; // 封闭图形填充的颜色 配合.fill()使用
ctx.lineTo(159,181); //从当前位置连一条线到指定位置(并不是真画线)
ctx.lineTo(5,69);
ctx.lineTo(195,69);
ctx.lineTo(41,181);
ctx.closePath();
ctx.strokeStyle = "red"; // 线条的颜色
ctx.stroke(); //画线条,作用是描边。
ctx.fill(); //填充封闭区域,使用指定的填充样式来填充
// 2.六边形
ctx.beginPath();
var jianbian2 = ctx.createLinearGradient(250,20,450,220); // 线性渐变————左上角到右下角渐变
jianbian2.addColorStop(0,"cyan");
jianbian2.addColorStop(0.3,"green");
jianbian2.addColorStop(0.7,"purple");
jianbian2.addColorStop(1,"blue");
ctx.fillStyle = jianbian2;
ctx.moveTo(300, 20);
ctx.lineTo(400,20);
ctx.lineTo(450, 120);
ctx.lineTo(400,220);
ctx.lineTo(300,220);
ctx.lineTo(250,120);
ctx.closePath();
ctx.strokeStyle = "black";
ctx.lineWidth = "3"; // 设置线条的粗细
ctx.stroke();
ctx.fill();
// 3.机器人头
ctx.beginPath(); // 开启新的路径
// 头轮廓
ctx.strokeRect(500,20,250,250);
//左眼
var jianbian3 = ctx.createRadialGradient(560,80,5,560,80,35); // 发散渐变——————指定两组圆心+半径:环内渐变
jianbian3.addColorStop(0,"red");
jianbian3.addColorStop(0.3,"blue");
jianbian3.addColorStop(0.7,"yellow");
jianbian3.addColorStop(1,"green");
ctx.fillStyle = jianbian3;
ctx.arc(560,80,35,0,Math.PI*2,true); // 150,500是圆心, 80是半径, 0是弧的起始角度, Math.PI/2是弧的结束角度, true是逆时针;false是顺时针.
//右眼
ctx.strokeRect(653,46,70,70);
//鼻子
ctx.moveTo(620,145);
ctx.lineTo(640,160);
ctx.lineTo(602,160);
ctx.closePath(); //从当前位置连接一条线,到起始位置,形成一个封闭路径
ctx.lineJoin = "round"; //线交点图形
ctx.stroke();
ctx.fill();
//嘴巴
ctx.beginPath();
var jianbian = ctx.createLinearGradient(568,220,683,220); // 线性渐变——————如果是一条直线,直接起点到终点渐变即可(注意:)
jianbian.addColorStop(0,"red");
jianbian.addColorStop(0.5,"blue");
jianbian.addColorStop(1,"yellow");
ctx.strokeStyle = jianbian;
ctx.lineWidth = 20;
ctx.moveTo(568,220);
ctx.lineTo(683,220);
ctx.lineCap = "round"; //线端点的显示效果
ctx.stroke();
// 4.空心五角形
ctx.beginPath();
ctx.lineWidth = 3;
ctx.strokeStyle = "black";
ctx.moveTo(750,300);
ctx.lineTo(790,380);
ctx.lineTo(870,380);
ctx.lineTo(800,430);
ctx.lineTo(840,520);
ctx.lineTo(750,460);
ctx.lineTo(670,520);
ctx.lineTo(700,430);
ctx.lineTo(630,380);
ctx.lineTo(710,380)
ctx.closePath();
ctx.stroke()
// 5.一个四肢健全的小人
ctx.beginPath();
// 脑袋
ctx.arc(1150,150,80,0,Math.PI*2,true);
// 身体
ctx.strokeRect(1070,230,160,250);
// 身体的纽扣
ctx.strokeRect(1143,290,10,20);
ctx.strokeRect(1143,350,10,20);
ctx.strokeRect(1143,410,10,20);
// 腿
ctx.strokeRect(1165,480,45,120);
ctx.strokeRect(1090,480,45,120);
// 脚
ctx.strokeRect(1158,600,60,25);
ctx.strokeRect(1082,600,60,25);
// 右胳膊+手
ctx.strokeRect(1230,290,110,35);
ctx.strokeRect(1310,325,30,78);
// 左胳膊+手
ctx.strokeRect(960,290,110,35);
ctx.strokeRect(960,325,30,78);
ctx.stroke();
// 小脸
ctx.beginPath();
// 左眼
ctx.arc(1115,125,20,0,Math.PI,true);
// 右眼
ctx.moveTo(1200,125);
ctx.arc(1180,125,20,0,Math.PI,true);
// 嘴巴
ctx.moveTo(1180,170);
ctx.arc(1150,170,30,0,Math.PI,false);
ctx.stroke();
</script>
</html>

3.高级阶段—一个小项目助你玩透canvas~
1️⃣难点:如何清除canvas画布上指定区域:
使用clearRect() 方法清空指定矩形区域。
JavaScript 语法:
context.clearRect(x,y,width,height)
| 参数 | 参数值 |
|---|---|
| x | 要清除的矩形左上角的 x 坐标 |
| y | 要清除的矩形左上角的 y 坐标 |
| width | 要清除的矩形的宽度 |
| height | 要清除的矩形的高度 |
⚠️难点解决——代码实现
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
#c{
border: 1px solid red;
}
</style>
</head>
<body>
<canvas id="c" width="1000" height="700"></canvas>
</body>
</body>
<script type="text/javascript">
var c = document.getElementById("c");
var ctx = c.getContext("2d");
// 填充整个canvas为lightgray颜色
ctx.fillStyle = "lightgray";
ctx.fillRect(0,0,1000,700);
// 清除指定区域中的内容
ctx.clearRect(100,100,100,100)
</script>
</html>
⚠️难点解决——实现效果

2️⃣项目——代码实现
实现效果—实现橡皮擦,即鼠标点下去移动所经过位置擦除,鼠标松开不清除。
-
本项目实现时需要注意的是:
-
在监听canvas的onmousemove事件(鼠标移动事件)时:
c.onmousemove = function(e){ e.clientX; e.pageX; c.offsetLeft; }
-
关于获取到的关于鼠标移动信息的几个量e.clientX; e.pageX;和 c.offsetLeft;都不能直接作为判断鼠标点击处区域的清除:
-
第一个原因是:上述几个量各自代表的含义如下:(它们的含义决定它们不是鼠标相对于canvas的真实坐标!)
-
-
e.clientX是鼠标距离网页窗口左边缘的距离 所以不能作为定位鼠标位置的量,因为窗口可以上下左右滑动,画布位置相对于窗口会变;
-
e.pageX是鼠标距离网页内容左边缘的距离;
-
c.offsetLeft是canvas相对于浏览器左边的距离
-
-
所以我们通过组合使用e.pageX和c.offsetLeft即可实现鼠标真实坐标的定位。在此要理解一个点是:canvas画布的坐标轴并不是直接与网页的坐标轴重合!所以才会有e.pageX(以网页的坐标轴为参考系)和c.offsetLeft(以canvas画布的坐标系为参考系)两种量。而我们只需要使用e.pageX-c.offsetLeft(理解为将canvas画布的坐标轴向左上网页的坐标轴平移直至重合)即可定位到鼠标的真实坐标。
-
第二个原因是:context.clearRect(x,y,w,h);方法清除的是指定坐标(x,y),宽w,高h的矩形区域。
-
注意:这个宽是指以(x,y)坐标向右x轴的长度;这个高是指以(x,y)坐标向下y轴的长度。所以我们定位到的鼠标坐标应该在x轴和y轴同时向左上canvas画布的原点处移动w/2和h/2个像素长。即e.pageX-c.offsetLeft - w/2,这就是清除区域的x坐标的推理过程。y坐标类似,小伙伴们自己多加思考哦。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
#c{
border: 1px solid red;
}
</style>
</head>
<body>
<canvas id="c" width="1000" height="700"></canvas>
</body>
<script type="text/javascript">
var c = document.getElementById("c");
var ctx = c.getContext("2d");
// 填充整个canvas为lightgray颜色
ctx.fillStyle = "lightgray";
ctx.fillRect(0,0,1000,700);
// 清除指定区域中的内容
//ctx.clearRect(100,100,100,100)
// 监听canvas的onmousedown事件(鼠标点击事件)
c.onmousedown = function(ev){
c.onmousemove = function(e){ // .onmousemove是鼠标移动事件
console.log(e); // 控制台打印e会发现它是鼠标移动所有信息的一个量
// e.clientX是鼠标距离网页窗口左边缘的距离 所以不能作为定位鼠标位置的量,因为窗口可以上下左右滑动,画布位置相对于窗口会变!
// e.clientY是鼠标距离网页窗口上边缘的距离
// e.pageX是鼠标距离网页内容左边缘的距离
// e.pageY是鼠标距离网页内容上边缘的距离
// c.offsetLeft是canvas相对于浏览器左边的距离
// c.offsetTop是canvas相对于浏览器上方的距离
var w = 20; // 清除区域的宽度
var h = 20; // 清除区域的高度
var x = e.pageX-c.offsetLeft - w/2; // 清除区域的x位置
var y = e.pageY-c.offsetTop - h/2; // 清除区域的y位置
ctx.clearRect(x,y,w,h);
}
}
c.onmouseup = function(ev){ // .onmouseup是鼠标松开事件
// 取消onmousemove事件
c.onmousemove = null;
}
</script>
</html>

1074

被折叠的 条评论
为什么被折叠?



