快速掌握canvas

(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)绘制一条直线

  1. 指定起始(x,y)坐标;

  2. 指定粗细;

  3. 指定颜色。 

注意:通过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)绘制一条折线

  1. 指定折点处的形状;

  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>

实现效果:

🚉拓展——几种复杂图形的绘制

  • 题目就是下面所列的五个,请小伙伴们发挥你们的小脑袋瓜,自己先动手绘制哦🙄!

  • 所用的操作在上面都已详细讲解,没有一道题超纲哦(实践是检验真理的唯一标准🤩)

  • 做完的小伙伴们可以看看下面我的代码和实现的效果,说不定你们做的比我的还要好😂!

  1. 使用红色填充的五角星;

  2. 使用渐变色填充的六边形;

  3. 机器人头部(使用线性渐变&&发散渐变);

  4. 空心的五角星;

  5. 绘制一个四肢健全的小人。

<!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的真实坐标!)

    1. e.clientX是鼠标距离网页窗口左边缘的距离     所以不能作为定位鼠标位置的量,因为窗口可以上下左右滑动,画布位置相对于窗口会变;

    2. e.pageX是鼠标距离网页内容左边缘的距离;

    3. 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>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值